From 9289f0a1b5f396366311306cd03d9c2bca1d74cd Mon Sep 17 00:00:00 2001 From: rstoyanchev Date: Wed, 30 Mar 2022 09:02:00 +0100 Subject: [PATCH] Add MockExecutionGraphQlService in testFixtures --- .../tester/GraphQlTesterBuilderTests.java | 11 +- .../test/tester/GraphQlTesterTestSupport.java | 67 ++------ .../test/tester/GraphQlTesterTests.java | 67 ++++---- .../RSocketGraphQlTesterBuilderTests.java | 39 +---- .../tester/WebGraphQlTesterBuilderTests.java | 33 ++-- spring-graphql/build.gradle | 1 + .../client/GraphQlClientBuilderTests.java | 4 +- .../client/GraphQlClientTestSupport.java | 78 ++------- .../graphql/client/GraphQlClientTests.java | 24 +-- .../RSocketGraphQlClientBuilderTests.java | 48 ++---- .../client/WebGraphQlClientBuilderTests.java | 74 ++++----- .../WebSocketGraphQlTransportTests.java | 2 - .../TestWebSocketClient.java | 2 +- .../TestWebSocketConnection.java | 2 +- .../MockExecutionGraphQlService.java | 151 ++++++++++++++++++ 15 files changed, 288 insertions(+), 315 deletions(-) rename spring-graphql/src/testFixtures/java/org/springframework/graphql/{server => client}/TestWebSocketClient.java (98%) rename spring-graphql/src/testFixtures/java/org/springframework/graphql/{server => client}/TestWebSocketConnection.java (99%) create mode 100644 spring-graphql/src/testFixtures/java/org/springframework/graphql/execution/MockExecutionGraphQlService.java diff --git a/spring-graphql-test/src/test/java/org/springframework/graphql/test/tester/GraphQlTesterBuilderTests.java b/spring-graphql-test/src/test/java/org/springframework/graphql/test/tester/GraphQlTesterBuilderTests.java index 51781c11..a47b59ad 100644 --- a/spring-graphql-test/src/test/java/org/springframework/graphql/test/tester/GraphQlTesterBuilderTests.java +++ b/spring-graphql-test/src/test/java/org/springframework/graphql/test/tester/GraphQlTesterBuilderTests.java @@ -41,20 +41,20 @@ public class GraphQlTesterBuilderTests extends GraphQlTesterTestSupport { DocumentSource documentSource = name -> name.equals("name") ? Mono.just(DOCUMENT) : Mono.error(new IllegalArgumentException()); - setMockResponse("{}"); + getGraphQlService().setDataAsJson(DOCUMENT, "{}"); // Original GraphQlTester.Builder builder = graphQlTesterBuilder().documentSource(documentSource); GraphQlTester tester = builder.build(); tester.documentName("name").execute(); - assertThat(request().getDocument()).isEqualTo(DOCUMENT); + assertThat(getActualRequestDocument()).isEqualTo(DOCUMENT); // Mutate tester = tester.mutate().build(); tester.documentName("name").execute(); - assertThat(request().getDocument()).isEqualTo(DOCUMENT); + assertThat(getActualRequestDocument()).isEqualTo(DOCUMENT); } @Test @@ -62,7 +62,8 @@ public class GraphQlTesterBuilderTests extends GraphQlTesterTestSupport { String document = "{me {name, friends}}"; - setMockResponse( + getGraphQlService().setErrors( + document, GraphqlErrorBuilder.newError().message("some error").build(), GraphqlErrorBuilder.newError().message("some other error").build()); @@ -74,7 +75,7 @@ public class GraphQlTesterBuilderTests extends GraphQlTesterTestSupport { .errors().verify() .path("me").pathDoesNotExist(); - assertThat(request().getDocument()).contains(document); + assertThat(getActualRequestDocument()).contains(document); } } diff --git a/spring-graphql-test/src/test/java/org/springframework/graphql/test/tester/GraphQlTesterTestSupport.java b/spring-graphql-test/src/test/java/org/springframework/graphql/test/tester/GraphQlTesterTestSupport.java index db255711..71412728 100644 --- a/spring-graphql-test/src/test/java/org/springframework/graphql/test/tester/GraphQlTesterTestSupport.java +++ b/spring-graphql-test/src/test/java/org/springframework/graphql/test/tester/GraphQlTesterTestSupport.java @@ -16,25 +16,8 @@ package org.springframework.graphql.test.tester; -import java.util.Arrays; -import java.util.Map; -import java.util.function.Consumer; +import org.springframework.graphql.execution.MockExecutionGraphQlService; -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.ObjectMapper; -import graphql.ExecutionInput; -import graphql.ExecutionResult; -import graphql.ExecutionResultImpl; -import graphql.GraphQLError; -import org.mockito.ArgumentCaptor; -import reactor.core.publisher.Mono; - -import org.springframework.graphql.ExecutionGraphQlRequest; -import org.springframework.graphql.ExecutionGraphQlService; -import org.springframework.graphql.support.DefaultExecutionGraphQlResponse; - -import static org.mockito.BDDMockito.given; -import static org.mockito.Mockito.mock; /** * Base class for {@link GraphQlTester} tests. @@ -43,18 +26,21 @@ import static org.mockito.Mockito.mock; */ public class GraphQlTesterTestSupport { - private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper(); - - - private final ArgumentCaptor requestCaptor = ArgumentCaptor.forClass(ExecutionGraphQlRequest.class); - - private final ExecutionGraphQlService graphQlService = mock(ExecutionGraphQlService.class); + private final MockExecutionGraphQlService graphQlService = new MockExecutionGraphQlService(); private final GraphQlTester.Builder graphQlTesterBuilder = ExecutionGraphQlServiceTester.builder(this.graphQlService); private final GraphQlTester graphQlTester = this.graphQlTesterBuilder.build(); + public MockExecutionGraphQlService getGraphQlService() { + return this.graphQlService; + } + + protected String getActualRequestDocument() { + return this.graphQlService.getGraphQlRequest().getDocument(); + } + protected GraphQlTester graphQlTester() { return this.graphQlTester; } @@ -63,37 +49,4 @@ public class GraphQlTesterTestSupport { return this.graphQlTesterBuilder; } - protected ExecutionGraphQlRequest request() { - return this.requestCaptor.getValue(); - } - - - protected void setMockResponse(String data) { - setMockResponse(builder -> serialize(data, builder)); - } - - protected void setMockResponse(GraphQLError... errors) { - setMockResponse(builder -> builder.errors(Arrays.asList(errors))); - } - - private void setMockResponse(Consumer consumer) { - - ExecutionResultImpl.Builder builder = new ExecutionResultImpl.Builder(); - consumer.accept(builder); - ExecutionInput executionInput = ExecutionInput.newExecutionInput("{}").build(); - ExecutionResult result = builder.build(); - - given(this.graphQlService.execute(this.requestCaptor.capture())) - .willReturn(Mono.just(new DefaultExecutionGraphQlResponse(executionInput, result))); - } - - private void serialize(String data, ExecutionResultImpl.Builder builder) { - try { - builder.data(OBJECT_MAPPER.readValue(data, Map.class)); - } - catch (JsonProcessingException ex) { - throw new IllegalStateException(ex); - } - } - } diff --git a/spring-graphql-test/src/test/java/org/springframework/graphql/test/tester/GraphQlTesterTests.java b/spring-graphql-test/src/test/java/org/springframework/graphql/test/tester/GraphQlTesterTests.java index 91aeaadb..ebdc282d 100644 --- a/spring-graphql-test/src/test/java/org/springframework/graphql/test/tester/GraphQlTesterTests.java +++ b/spring-graphql-test/src/test/java/org/springframework/graphql/test/tester/GraphQlTesterTests.java @@ -43,7 +43,7 @@ public class GraphQlTesterTests extends GraphQlTesterTestSupport { void hasValue() { String document = "{me {name, friends}}"; - setMockResponse("{\"me\": {\"name\":\"Luke Skywalker\", \"friends\":[]}}"); + getGraphQlService().setDataAsJson(document, "{\"me\": {\"name\":\"Luke Skywalker\", \"friends\":[]}}"); GraphQlTester.Response response = graphQlTester().document(document).execute(); response.path("me.name").hasValue(); @@ -52,14 +52,14 @@ public class GraphQlTesterTests extends GraphQlTesterTestSupport { assertThatThrownBy(() -> response.path("hero").hasValue()) .hasMessageContaining("No value at JSON path \"$['data']['hero']"); - assertThat(request().getDocument()).contains(document); + assertThat(getActualRequestDocument()).contains(document); } @Test void valueIsNull() { String document = "{me {name, friends}}"; - setMockResponse("{\"me\": {\"name\":null, \"friends\":null}}"); + getGraphQlService().setDataAsJson(document, "{\"me\": {\"name\":null, \"friends\":null}}"); GraphQlTester.Response response = graphQlTester().document(document).execute(); @@ -69,14 +69,14 @@ public class GraphQlTesterTests extends GraphQlTesterTestSupport { assertThatThrownBy(() -> response.path("me").valueIsNull()) .hasMessageContaining("Expected null value at JSON path"); - assertThat(request().getDocument()).contains(document); + assertThat(getActualRequestDocument()).contains(document); } @Test void valueIsEmptyList() { String document = "{me {name, friends}}"; - setMockResponse("{\"me\": {\"name\":\"Luke Skywalker\", \"friends\":[]}}"); + getGraphQlService().setDataAsJson(document, "{\"me\": {\"name\":\"Luke Skywalker\", \"friends\":[]}}"); GraphQlTester.Response response = graphQlTester().document(document).execute(); response.path("me.friends").hasValue().entityList(MovieCharacter.class).hasSize(0); @@ -85,7 +85,7 @@ public class GraphQlTesterTests extends GraphQlTesterTestSupport { @Test void pathDoesNotExist() { String document = "{me {name, friends}}"; - setMockResponse("{\"me\": {\"name\":\"Luke Skywalker\", \"friends\":[]}}"); + getGraphQlService().setDataAsJson(document, "{\"me\": {\"name\":\"Luke Skywalker\", \"friends\":[]}}"); GraphQlTester.Response response = graphQlTester().document(document).execute(); @@ -99,7 +99,7 @@ public class GraphQlTesterTests extends GraphQlTesterTestSupport { void matchesJson() { String document = "{me {name}}"; - setMockResponse("{\"me\": {\"name\":\"Luke Skywalker\", \"friends\":[]}}"); + getGraphQlService().setDataAsJson(document, "{\"me\": {\"name\":\"Luke Skywalker\", \"friends\":[]}}"); GraphQlTester.Response response = graphQlTester().document(document).execute(); @@ -111,14 +111,14 @@ public class GraphQlTesterTests extends GraphQlTesterTestSupport { .as("Extended fields should fail in strict mode") .hasMessageContaining("Unexpected: name"); - assertThat(request().getDocument()).contains(document); + assertThat(getActualRequestDocument()).contains(document); } @Test void entity() { String document = "{me {name}}"; - setMockResponse("{\"me\": {\"name\":\"Luke Skywalker\"}}"); + getGraphQlService().setDataAsJson(document, "{\"me\": {\"name\":\"Luke Skywalker\"}}"); GraphQlTester.Response response = graphQlTester().document(document).execute(); @@ -141,14 +141,15 @@ public class GraphQlTesterTests extends GraphQlTesterTestSupport { .entity(new ParameterizedTypeReference>() {}) .isEqualTo(Collections.singletonMap("me", luke)); - assertThat(request().getDocument()).contains(document); + assertThat(getActualRequestDocument()).contains(document); } @Test void entityList() { String document = "{me {name, friends}}"; - setMockResponse("{" + + getGraphQlService().setDataAsJson(document, + "{" + " \"me\":{" + " \"name\":\"Luke Skywalker\"," + " \"friends\":[{\"name\":\"Han Solo\"}, {\"name\":\"Leia Organa\"}]" + @@ -183,7 +184,7 @@ public class GraphQlTesterTests extends GraphQlTesterTestSupport { .entityList(new ParameterizedTypeReference() {}) .containsExactly(han, leia); - assertThat(request().getDocument()).contains(document); + assertThat(getActualRequestDocument()).contains(document); } @Test @@ -195,7 +196,7 @@ public class GraphQlTesterTests extends GraphQlTesterTestSupport { + " }" + "}"; - setMockResponse("{\"hero\": {\"name\":\"R2-D2\"}}"); + getGraphQlService().setDataAsJson(document, "{\"hero\": {\"name\":\"R2-D2\"}}"); GraphQlTester.Response response = graphQlTester().document(document) .operationName("HeroNameAndFriends") @@ -206,7 +207,7 @@ public class GraphQlTesterTests extends GraphQlTesterTestSupport { response.path("hero").entity(MovieCharacter.class).isEqualTo(MovieCharacter.create("R2-D2")); - ExecutionGraphQlRequest request = request(); + ExecutionGraphQlRequest request = getGraphQlService().getGraphQlRequest(); assertThat(request.getDocument()).contains(document); assertThat(request.getOperationName()).isEqualTo("HeroNameAndFriends"); assertThat(request.getVariables()).hasSize(3); @@ -219,42 +220,43 @@ public class GraphQlTesterTests extends GraphQlTesterTestSupport { void errorsEmptyOnExecuteAndVerify() { String document = "{me {name, friends}}"; - setMockResponse("{\"me\": {\"name\":\"Luke Skywalker\", \"friends\":[]}}"); + getGraphQlService().setDataAsJson(document, "{\"me\": {\"name\":\"Luke Skywalker\", \"friends\":[]}}"); graphQlTester().document(document).executeAndVerify(); - assertThat(request().getDocument()).contains(document); + assertThat(getActualRequestDocument()).contains(document); } @Test void errorsCheckedOnExecuteAndVerify() { String document = "{me {name, friends}}"; - setMockResponse(GraphqlErrorBuilder.newError().message("Invalid query").build()); + getGraphQlService().setError(document, builder -> builder.message("Invalid query")); assertThatThrownBy(() -> graphQlTester().document(document).executeAndVerify()) .hasMessageContaining("Response has 1 unexpected error(s)"); - assertThat(request().getDocument()).contains(document); + assertThat(getActualRequestDocument()).contains(document); } @Test void errorsCheckedOnTraverse() { String document = "{me {name, friends}}"; - setMockResponse(GraphqlErrorBuilder.newError().message("Invalid query").build()); + getGraphQlService().setError(document, builder -> builder.message("Invalid query")); assertThatThrownBy(() -> graphQlTester().document(document).execute().path("me")) .hasMessageContaining("Response has 1 unexpected error(s)"); - assertThat(request().getDocument()).contains(document); + assertThat(getActualRequestDocument()).contains(document); } @Test void errorsPartiallyFiltered() { String document = "{me {name, friends}}"; - setMockResponse( + getGraphQlService().setErrors( + document, GraphqlErrorBuilder.newError().message("some error").build(), GraphqlErrorBuilder.newError().message("some other error").build()); @@ -266,14 +268,15 @@ public class GraphQlTesterTests extends GraphQlTesterTestSupport { .verify()) .hasMessageContaining("Response has 1 unexpected error(s) of 2 total."); - assertThat(request().getDocument()).contains(document); + assertThat(getActualRequestDocument()).contains(document); } @Test void errorsFiltered() { String document = "{me {name, friends}}"; - setMockResponse( + getGraphQlService().setErrors( + document, GraphqlErrorBuilder.newError().message("some error").build(), GraphqlErrorBuilder.newError().message("some other error").build()); @@ -285,14 +288,15 @@ public class GraphQlTesterTests extends GraphQlTesterTestSupport { .path("me") .pathDoesNotExist(); - assertThat(request().getDocument()).contains(document); + assertThat(getActualRequestDocument()).contains(document); } @Test void errorsExpected() { String document = "{me {name, friends}}"; - setMockResponse( + getGraphQlService().setErrors( + document, GraphqlErrorBuilder.newError().message("some error").build(), GraphqlErrorBuilder.newError().message("some other error").build()); @@ -303,14 +307,15 @@ public class GraphQlTesterTests extends GraphQlTesterTestSupport { .verify() .path("me").pathDoesNotExist(); - assertThat(request().getDocument()).contains(document); + assertThat(getActualRequestDocument()).contains(document); } @Test void errorsExpectedButNotFound() { String document = "{me {name, friends}}"; - setMockResponse( + getGraphQlService().setErrors( + document, GraphqlErrorBuilder.newError().message("some error").build(), GraphqlErrorBuilder.newError().message("some other error").build()); @@ -325,10 +330,8 @@ public class GraphQlTesterTests extends GraphQlTesterTestSupport { void errorsConsumed() { String document = "{me {name, friends}}"; - setMockResponse(GraphqlErrorBuilder.newError() - .message("Invalid query") - .location(new SourceLocation(1, 2)) - .build()); + getGraphQlService().setError(document, builder -> + builder.message("Invalid query").location(new SourceLocation(1, 2)).build()); graphQlTester().document(document) .execute() @@ -342,7 +345,7 @@ public class GraphQlTesterTests extends GraphQlTesterTestSupport { }) .path("me").pathDoesNotExist(); - assertThat(request().getDocument()).contains(document); + assertThat(getActualRequestDocument()).contains(document); } } diff --git a/spring-graphql-test/src/test/java/org/springframework/graphql/test/tester/RSocketGraphQlTesterBuilderTests.java b/spring-graphql-test/src/test/java/org/springframework/graphql/test/tester/RSocketGraphQlTesterBuilderTests.java index 5cddf603..70616185 100644 --- a/spring-graphql-test/src/test/java/org/springframework/graphql/test/tester/RSocketGraphQlTesterBuilderTests.java +++ b/spring-graphql-test/src/test/java/org/springframework/graphql/test/tester/RSocketGraphQlTesterBuilderTests.java @@ -17,11 +17,8 @@ package org.springframework.graphql.test.tester; import java.util.Collections; -import java.util.HashMap; import java.util.Map; -import graphql.ExecutionInput; -import graphql.ExecutionResult; import graphql.ExecutionResultImpl; import io.rsocket.Closeable; import io.rsocket.SocketAcceptor; @@ -36,11 +33,9 @@ import reactor.core.publisher.Mono; import org.springframework.core.ResolvableType; import org.springframework.core.codec.DecodingException; import org.springframework.core.io.buffer.DataBuffer; -import org.springframework.graphql.ExecutionGraphQlResponse; -import org.springframework.graphql.ExecutionGraphQlService; import org.springframework.graphql.GraphQlRequest; +import org.springframework.graphql.execution.MockExecutionGraphQlService; import org.springframework.graphql.server.GraphQlRSocketHandler; -import org.springframework.graphql.support.DefaultExecutionGraphQlResponse; import org.springframework.http.codec.json.Jackson2JsonDecoder; import org.springframework.http.codec.json.Jackson2JsonEncoder; import org.springframework.lang.Nullable; @@ -48,7 +43,6 @@ import org.springframework.messaging.handler.annotation.MessageMapping; import org.springframework.messaging.rsocket.RSocketStrategies; import org.springframework.messaging.rsocket.annotation.support.RSocketMessageHandler; import org.springframework.stereotype.Controller; -import org.springframework.util.Assert; import org.springframework.util.MimeType; import static org.assertj.core.api.Assertions.assertThat; @@ -106,7 +100,7 @@ public class RSocketGraphQlTesterBuilderTests { String document = "{me {name}}"; MovieCharacter character = MovieCharacter.create("Luke Skywalker"); - this.builderSetup.setMockResponse(document, + this.builderSetup.getGraphQlService().setResponse(document, ExecutionResultImpl.newExecutionResult() .data(Collections.singletonMap("me", character)) .build()); @@ -126,34 +120,19 @@ public class RSocketGraphQlTesterBuilderTests { private static class BuilderSetup { - private GraphQlRequest graphQlRequest; - - private final Map responses = new HashMap<>(); + private final MockExecutionGraphQlService graphQlService = new MockExecutionGraphQlService(); @Nullable private Closeable server; public BuilderSetup() { - - ExecutionGraphQlResponse defaultResponse = new DefaultExecutionGraphQlResponse( - ExecutionInput.newExecutionInput().query(DOCUMENT).build(), - ExecutionResultImpl.newExecutionResult().build()); - - this.responses.put(DOCUMENT, defaultResponse); + this.graphQlService.setDefaultDataAsJson("{}"); } public RSocketGraphQlTester.Builder initBuilder() { - ExecutionGraphQlService graphQlService = request -> { - this.graphQlRequest = request; - String document = request.getDocument(); - ExecutionGraphQlResponse response = this.responses.get(document); - Assert.notNull(response, "Unexpected request: " + document); - return Mono.just(response); - }; - GraphQlRSocketController controller = new GraphQlRSocketController( - new GraphQlRSocketHandler(graphQlService, Collections.emptyList(), new Jackson2JsonEncoder())); + new GraphQlRSocketHandler(this.graphQlService, Collections.emptyList(), new Jackson2JsonEncoder())); this.server = RSocketServer.create() .acceptor(createSocketAcceptor(controller)) @@ -178,14 +157,12 @@ public class RSocketGraphQlTesterBuilderTests { return handler.responder(); } - @SuppressWarnings("unused") - public void setMockResponse(String document, ExecutionResult result) { - ExecutionInput executionInput = ExecutionInput.newExecutionInput().query(document).build(); - this.responses.put(document, new DefaultExecutionGraphQlResponse(executionInput, result)); + public MockExecutionGraphQlService getGraphQlService() { + return this.graphQlService; } public GraphQlRequest getGraphQlRequest() { - return this.graphQlRequest; + return this.graphQlService.getGraphQlRequest(); } public void shutDown() { diff --git a/spring-graphql-test/src/test/java/org/springframework/graphql/test/tester/WebGraphQlTesterBuilderTests.java b/spring-graphql-test/src/test/java/org/springframework/graphql/test/tester/WebGraphQlTesterBuilderTests.java index 14b96c47..3f9f84de 100644 --- a/spring-graphql-test/src/test/java/org/springframework/graphql/test/tester/WebGraphQlTesterBuilderTests.java +++ b/spring-graphql-test/src/test/java/org/springframework/graphql/test/tester/WebGraphQlTesterBuilderTests.java @@ -19,11 +19,9 @@ package org.springframework.graphql.test.tester; import java.net.URI; import java.time.Duration; import java.util.Collections; -import java.util.HashMap; import java.util.Map; import java.util.stream.Stream; -import graphql.ExecutionInput; import graphql.ExecutionResult; import graphql.ExecutionResultImpl; import org.junit.jupiter.api.Test; @@ -34,21 +32,19 @@ import reactor.core.publisher.Mono; import org.springframework.core.ResolvableType; import org.springframework.core.codec.DecodingException; import org.springframework.core.io.buffer.DataBuffer; -import org.springframework.graphql.ExecutionGraphQlResponse; -import org.springframework.graphql.support.DefaultExecutionGraphQlResponse; -import org.springframework.graphql.support.DocumentSource; -import org.springframework.graphql.server.WebGraphQlRequest; -import org.springframework.graphql.server.TestWebSocketClient; -import org.springframework.graphql.server.TestWebSocketConnection; +import org.springframework.graphql.client.TestWebSocketClient; +import org.springframework.graphql.client.TestWebSocketConnection; +import org.springframework.graphql.execution.MockExecutionGraphQlService; import org.springframework.graphql.server.WebGraphQlHandler; import org.springframework.graphql.server.WebGraphQlInterceptor; +import org.springframework.graphql.server.WebGraphQlRequest; import org.springframework.graphql.server.webflux.GraphQlHttpHandler; import org.springframework.graphql.server.webflux.GraphQlWebSocketHandler; +import org.springframework.graphql.support.DocumentSource; import org.springframework.http.codec.ClientCodecConfigurer; import org.springframework.http.codec.json.Jackson2JsonDecoder; import org.springframework.lang.Nullable; import org.springframework.test.web.reactive.server.WebTestClient; -import org.springframework.util.Assert; import org.springframework.util.MimeType; import org.springframework.web.reactive.function.server.RouterFunction; import org.springframework.web.reactive.function.server.ServerResponse; @@ -211,15 +207,10 @@ public class WebGraphQlTesterBuilderTests { private WebGraphQlRequest request; - private final Map responses = new HashMap<>(); + private final MockExecutionGraphQlService graphQlService = new MockExecutionGraphQlService(); public WebBuilderSetup() { - - ExecutionGraphQlResponse defaultResponse = new DefaultExecutionGraphQlResponse( - ExecutionInput.newExecutionInput().query(DOCUMENT).build(), - ExecutionResultImpl.newExecutionResult().build()); - - this.responses.put(DOCUMENT, defaultResponse); + this.graphQlService.setDefaultDataAsJson("{}"); } @Override @@ -228,12 +219,7 @@ public class WebGraphQlTesterBuilderTests { } protected WebGraphQlHandler webGraphQlHandler() { - return WebGraphQlHandler.builder(request -> { - String document = request.getDocument(); - ExecutionGraphQlResponse response = this.responses.get(document); - Assert.notNull(response, "Unexpected request: " + document); - return Mono.just(response); - }) + return WebGraphQlHandler.builder(this.graphQlService) .interceptor((input, chain) -> { this.request = input; return chain.next(request); @@ -243,8 +229,7 @@ public class WebGraphQlTesterBuilderTests { @Override public void setMockResponse(String document, ExecutionResult result) { - ExecutionInput executionInput = ExecutionInput.newExecutionInput().query(document).build(); - this.responses.put(document, new DefaultExecutionGraphQlResponse(executionInput, result)); + this.graphQlService.setResponse(document, result); } @Override diff --git a/spring-graphql/build.gradle b/spring-graphql/build.gradle index 62f549bd..192ef76f 100644 --- a/spring-graphql/build.gradle +++ b/spring-graphql/build.gradle @@ -64,6 +64,7 @@ dependencies { testRuntimeOnly 'org.apache.logging.log4j:log4j-slf4j-impl' testFixturesApi 'org.springframework:spring-webflux' + testFixturesApi 'com.fasterxml.jackson.core:jackson-databind' } test { diff --git a/spring-graphql/src/test/java/org/springframework/graphql/client/GraphQlClientBuilderTests.java b/spring-graphql/src/test/java/org/springframework/graphql/client/GraphQlClientBuilderTests.java index 5436b522..c88d0e36 100644 --- a/spring-graphql/src/test/java/org/springframework/graphql/client/GraphQlClientBuilderTests.java +++ b/spring-graphql/src/test/java/org/springframework/graphql/client/GraphQlClientBuilderTests.java @@ -44,7 +44,7 @@ public class GraphQlClientBuilderTests extends GraphQlClientTestSupport { DocumentSource documentSource = name -> name.equals("name") ? Mono.just(DOCUMENT) : Mono.error(new IllegalArgumentException()); - initDataResponse(DOCUMENT, "{}"); + getGraphQlService().setDataAsJson(DOCUMENT, "{}"); // Original GraphQlClient.Builder builder = graphQlClientBuilder().documentSource(documentSource); @@ -76,7 +76,7 @@ public class GraphQlClientBuilderTests extends GraphQlClientTestSupport { GraphQlClientInterceptor changingInterceptor = initInterceptor(request -> request.getAttributes().computeIfPresent(name, (k, v) -> v + "2")); - initDataResponse(DOCUMENT, "{}"); + getGraphQlService().setDataAsJson(DOCUMENT, "{}"); // Original GraphQlClient.Builder builder = graphQlClientBuilder().interceptor(savingInterceptor); diff --git a/spring-graphql/src/test/java/org/springframework/graphql/client/GraphQlClientTestSupport.java b/spring-graphql/src/test/java/org/springframework/graphql/client/GraphQlClientTestSupport.java index e57be3ab..23778178 100644 --- a/spring-graphql/src/test/java/org/springframework/graphql/client/GraphQlClientTestSupport.java +++ b/spring-graphql/src/test/java/org/springframework/graphql/client/GraphQlClientTestSupport.java @@ -17,25 +17,9 @@ package org.springframework.graphql.client; import java.time.Duration; -import java.util.Arrays; -import java.util.Map; -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.ObjectMapper; -import graphql.ExecutionResult; -import graphql.ExecutionResultImpl; -import graphql.GraphQLError; -import org.mockito.ArgumentCaptor; -import reactor.core.publisher.Mono; - -import org.springframework.graphql.support.DefaultGraphQlRequest; import org.springframework.graphql.GraphQlRequest; -import org.springframework.lang.Nullable; -import org.springframework.util.ObjectUtils; - -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; +import org.springframework.graphql.execution.MockExecutionGraphQlService; /** * Base class for {@link GraphQlClient} tests. @@ -46,67 +30,27 @@ public class GraphQlClientTestSupport { protected static final Duration TIMEOUT = Duration.ofSeconds(5); + private final MockExecutionGraphQlService graphQlService = new MockExecutionGraphQlService(); - private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper(); + private final GraphQlClient.Builder clientBuilder = GraphQlClient.builder(this.graphQlService.asGraphQlTransport()); - - private final ArgumentCaptor requestCaptor = ArgumentCaptor.forClass(DefaultGraphQlRequest.class); - - private final GraphQlTransport transport = mock(GraphQlTransport.class); - - private final GraphQlClient.Builder graphQlClientBuilder = GraphQlClient.builder(this.transport); - - private final GraphQlClient graphQlClient = this.graphQlClientBuilder.build(); + private final GraphQlClient client = this.clientBuilder.build(); protected GraphQlClient graphQlClient() { - return this.graphQlClient; + return this.client; } public GraphQlClient.Builder graphQlClientBuilder() { - return this.graphQlClientBuilder; + return this.clientBuilder; + } + + public MockExecutionGraphQlService getGraphQlService() { + return this.graphQlService; } protected GraphQlRequest request() { - return this.requestCaptor.getValue(); - } - - - protected void initDataResponse(String document, String responseData) { - initResponse(new DefaultGraphQlRequest(document), responseData); - } - - protected void initErrorResponse(String document, GraphQLError... errors) { - initResponse(new DefaultGraphQlRequest(document), null, errors); - } - - protected void initResponse(String document, String responseData, GraphQLError... errors) { - initResponse(new DefaultGraphQlRequest(document), responseData, errors); - } - - protected void initResponse(GraphQlRequest request, @Nullable String responseData, GraphQLError... errors) { - ExecutionResultImpl.Builder builder = new ExecutionResultImpl.Builder(); - if (responseData != null) { - builder.data(decode(responseData)); - } - if (!ObjectUtils.isEmpty(errors)) { - builder.errors(Arrays.asList(errors)); - } - ExecutionResult executionResult = builder.build(); - Map responseMap = executionResult.toSpecification(); - - when(this.transport.execute(eq(request))) - .thenReturn(Mono.just(new ResponseMapGraphQlResponse(responseMap))); - } - - @SuppressWarnings("unchecked") - private T decode(String data) { - try { - return (T) OBJECT_MAPPER.readValue(data, Map.class); - } - catch (JsonProcessingException ex) { - throw new IllegalStateException(ex); - } + return this.graphQlService.getGraphQlRequest(); } } diff --git a/spring-graphql/src/test/java/org/springframework/graphql/client/GraphQlClientTests.java b/spring-graphql/src/test/java/org/springframework/graphql/client/GraphQlClientTests.java index 68ef608a..f65b5e9a 100644 --- a/spring-graphql/src/test/java/org/springframework/graphql/client/GraphQlClientTests.java +++ b/spring-graphql/src/test/java/org/springframework/graphql/client/GraphQlClientTests.java @@ -30,8 +30,8 @@ import graphql.validation.ValidationErrorType; import org.junit.jupiter.api.Test; import org.springframework.core.ParameterizedTypeReference; -import org.springframework.graphql.support.DefaultGraphQlRequest; import org.springframework.graphql.GraphQlRequest; +import org.springframework.graphql.support.DefaultGraphQlRequest; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; @@ -48,7 +48,7 @@ public class GraphQlClientTests extends GraphQlClientTestSupport { void retrieveEntity() { String document = "mockRequest1"; - initDataResponse(document, "{\"me\": {\"name\":\"Luke Skywalker\"}}"); + getGraphQlService().setDataAsJson(document, "{\"me\": {\"name\":\"Luke Skywalker\"}}"); MovieCharacter movieCharacter = graphQlClient().document(document) .retrieve("me").toEntity(MovieCharacter.class) @@ -61,7 +61,7 @@ public class GraphQlClientTests extends GraphQlClientTestSupport { void retrieveEntityList() { String document = "mockRequest1"; - initDataResponse(document, "{" + + getGraphQlService().setDataAsJson(document, "{" + " \"me\":{" + " \"name\":\"Luke Skywalker\"," + " \"friends\":[{\"name\":\"Han Solo\"}, {\"name\":\"Leia Organa\"}]" + @@ -81,7 +81,7 @@ public class GraphQlClientTests extends GraphQlClientTestSupport { void retrieveAndDecodeDataMap() { String document = "mockRequest1"; - initDataResponse(document, "{\"me\": {\"name\":\"Luke Skywalker\"}}"); + getGraphQlService().setDataAsJson(document, "{\"me\": {\"name\":\"Luke Skywalker\"}}"); Map map = graphQlClient().document(document) .retrieve("").toEntity(new ParameterizedTypeReference>() {}) @@ -102,7 +102,7 @@ public class GraphQlClientTests extends GraphQlClientTestSupport { vars.put("keyOnly", null); GraphQlRequest request = new DefaultGraphQlRequest("mockRequest1", "HeroNameAndFriends", vars); - initResponse(request, "{\"hero\": {\"name\":\"R2-D2\"}}"); + getGraphQlService().setDataAsJson(request.getDocument(), "{\"hero\": {\"name\":\"R2-D2\"}}"); MovieCharacter character = graphQlClient().document(document) .operationName(operationName) @@ -119,12 +119,13 @@ public class GraphQlClientTests extends GraphQlClientTestSupport { void retrieveInvalidResponse() { String document = "errorsOnlyResponse"; - initErrorResponse(document, new ValidationError(ValidationErrorType.InvalidSyntax)); + getGraphQlService().setErrors(document, new ValidationError(ValidationErrorType.InvalidSyntax)); testRetrieveFieldAccessException(document, "me"); document = "nullDataResponse"; GraphQLObjectType type = GraphQLObjectType.newObject().name("n").build(); - initResponse(document, "null", new NonNullableValueCoercedAsNullException("f", new ArrayList<>(), type)); + GraphQLError error = new NonNullableValueCoercedAsNullException("f", new ArrayList<>(), type); + getGraphQlService().setDataAsJsonAndErrors(document, "null", error); testRetrieveFieldAccessException(document, "me"); } @@ -132,7 +133,7 @@ public class GraphQlClientTests extends GraphQlClientTestSupport { void retrievePartialResponse() { String document = "fieldErrorResponse"; - initResponse(document, "{\"me\": {\"name\":null}}", errorForPath("/me/name")); + getGraphQlService().setDataAsJsonAndErrors(document, "{\"me\": {\"name\":null}}", errorForPath("/me/name")); MovieCharacter character = graphQlClient().document(document).retrieve("me").toEntity(MovieCharacter.class).block(); assertThat(character).isNotNull().extracting(MovieCharacter::getName).isNull(); @@ -152,12 +153,13 @@ public class GraphQlClientTests extends GraphQlClientTestSupport { void executeInvalidResponse() { String document = "errorsOnlyResponse"; - initErrorResponse(document, new ValidationError(ValidationErrorType.InvalidSyntax)); + getGraphQlService().setErrors(document, new ValidationError(ValidationErrorType.InvalidSyntax)); testExecuteFailedResponse(document); document = "nullDataResponse"; GraphQLObjectType type = GraphQLObjectType.newObject().name("n").build(); - initResponse(document, "null", new NonNullableValueCoercedAsNullException("f", new ArrayList<>(), type)); + GraphQLError error = new NonNullableValueCoercedAsNullException("f", new ArrayList<>(), type); + getGraphQlService().setDataAsJsonAndErrors(document, "null", error); testExecuteFailedResponse(document); } @@ -178,7 +180,7 @@ public class GraphQlClientTests extends GraphQlClientTestSupport { void executePartialResponse() { String document = "fieldErrorResponse"; - initResponse(document, "{\"me\": {\"name\":null}}", errorForPath("/me/name")); + getGraphQlService().setDataAsJsonAndErrors(document, "{\"me\": {\"name\":null}}", errorForPath("/me/name")); testRetrieveFieldAccessException(document, "me.name"); ClientGraphQlResponse response = diff --git a/spring-graphql/src/test/java/org/springframework/graphql/client/RSocketGraphQlClientBuilderTests.java b/spring-graphql/src/test/java/org/springframework/graphql/client/RSocketGraphQlClientBuilderTests.java index 9bdb48b4..69be8fd9 100644 --- a/spring-graphql/src/test/java/org/springframework/graphql/client/RSocketGraphQlClientBuilderTests.java +++ b/spring-graphql/src/test/java/org/springframework/graphql/client/RSocketGraphQlClientBuilderTests.java @@ -18,12 +18,8 @@ package org.springframework.graphql.client; import java.time.Duration; import java.util.Collections; -import java.util.HashMap; import java.util.Map; -import graphql.ExecutionInput; -import graphql.ExecutionResult; -import graphql.ExecutionResultImpl; import io.rsocket.Closeable; import io.rsocket.SocketAcceptor; import io.rsocket.core.RSocketServer; @@ -34,11 +30,9 @@ import org.junit.jupiter.api.Test; import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; -import org.springframework.graphql.ExecutionGraphQlResponse; -import org.springframework.graphql.ExecutionGraphQlService; import org.springframework.graphql.GraphQlRequest; +import org.springframework.graphql.execution.MockExecutionGraphQlService; import org.springframework.graphql.server.GraphQlRSocketHandler; -import org.springframework.graphql.support.DefaultExecutionGraphQlResponse; import org.springframework.http.codec.json.Jackson2JsonDecoder; import org.springframework.http.codec.json.Jackson2JsonEncoder; import org.springframework.lang.Nullable; @@ -46,7 +40,6 @@ import org.springframework.messaging.handler.annotation.MessageMapping; import org.springframework.messaging.rsocket.RSocketStrategies; import org.springframework.messaging.rsocket.annotation.support.RSocketMessageHandler; import org.springframework.stereotype.Controller; -import org.springframework.util.Assert; import static org.assertj.core.api.Assertions.assertThat; @@ -81,48 +74,41 @@ public class RSocketGraphQlClientBuilderTests { RSocketGraphQlClient client = builder.build(); client.document(DOCUMENT).execute().block(TIMEOUT); - GraphQlRequest request = this.builderSetup.getGraphQlRequest(); + GraphQlRequest request = this.builderSetup.getActualRequest(); assertThat(request).isNotNull(); // Mutate: still works (carries over original default) client = client.mutate().build(); client.document(DOCUMENT).execute().block(TIMEOUT); - request = this.builderSetup.getGraphQlRequest(); + request = this.builderSetup.getActualRequest(); assertThat(request).isNotNull(); } private static class BuilderSetup { - private GraphQlRequest graphQlRequest; - - private final Map responses = new HashMap<>(); + private final MockExecutionGraphQlService graphQlService = new MockExecutionGraphQlService(); @Nullable private Closeable server; public BuilderSetup() { + this.graphQlService.setDefaultDataAsJson("{}"); + } - ExecutionGraphQlResponse defaultResponse = new DefaultExecutionGraphQlResponse( - ExecutionInput.newExecutionInput().query(DOCUMENT).build(), - ExecutionResultImpl.newExecutionResult().build()); + public MockExecutionGraphQlService getGraphQlService() { + return this.graphQlService; + } - this.responses.put(DOCUMENT, defaultResponse); + public GraphQlRequest getActualRequest() { + return this.graphQlService.getGraphQlRequest(); } public RSocketGraphQlClient.Builder initBuilder() { - ExecutionGraphQlService graphQlService = request -> { - this.graphQlRequest = request; - String document = request.getDocument(); - ExecutionGraphQlResponse response = this.responses.get(document); - Assert.notNull(response, "Unexpected request: " + document); - return Mono.just(response); - }; - GraphQlRSocketController controller = new GraphQlRSocketController( - new GraphQlRSocketHandler(graphQlService, Collections.emptyList(), new Jackson2JsonEncoder())); + new GraphQlRSocketHandler(this.graphQlService, Collections.emptyList(), new Jackson2JsonEncoder())); this.server = RSocketServer.create() .acceptor(createSocketAcceptor(controller)) @@ -147,16 +133,6 @@ public class RSocketGraphQlClientBuilderTests { return handler.responder(); } - @SuppressWarnings("unused") - public void setMockResponse(String document, ExecutionResult result) { - ExecutionInput executionInput = ExecutionInput.newExecutionInput().query(document).build(); - this.responses.put(document, new DefaultExecutionGraphQlResponse(executionInput, result)); - } - - public GraphQlRequest getGraphQlRequest() { - return this.graphQlRequest; - } - public void shutDown() { if (this.server != null) { this.server.dispose(); diff --git a/spring-graphql/src/test/java/org/springframework/graphql/client/WebGraphQlClientBuilderTests.java b/spring-graphql/src/test/java/org/springframework/graphql/client/WebGraphQlClientBuilderTests.java index 95a9b302..414d01c9 100644 --- a/spring-graphql/src/test/java/org/springframework/graphql/client/WebGraphQlClientBuilderTests.java +++ b/spring-graphql/src/test/java/org/springframework/graphql/client/WebGraphQlClientBuilderTests.java @@ -19,12 +19,9 @@ package org.springframework.graphql.client; import java.net.URI; import java.time.Duration; import java.util.Collections; -import java.util.HashMap; import java.util.Map; import java.util.stream.Stream; -import graphql.ExecutionInput; -import graphql.ExecutionResult; import graphql.ExecutionResultImpl; import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; @@ -34,22 +31,18 @@ import reactor.core.publisher.Mono; import org.springframework.core.ResolvableType; import org.springframework.core.codec.DecodingException; import org.springframework.core.io.buffer.DataBuffer; -import org.springframework.graphql.ExecutionGraphQlResponse; -import org.springframework.graphql.support.DefaultExecutionGraphQlResponse; -import org.springframework.graphql.support.DocumentSource; -import org.springframework.graphql.server.WebGraphQlRequest; -import org.springframework.graphql.server.TestWebSocketClient; -import org.springframework.graphql.server.TestWebSocketConnection; +import org.springframework.graphql.execution.MockExecutionGraphQlService; import org.springframework.graphql.server.WebGraphQlHandler; import org.springframework.graphql.server.WebGraphQlInterceptor; +import org.springframework.graphql.server.WebGraphQlRequest; import org.springframework.graphql.server.webflux.GraphQlHttpHandler; import org.springframework.graphql.server.webflux.GraphQlWebSocketHandler; +import org.springframework.graphql.support.DocumentSource; import org.springframework.http.codec.ClientCodecConfigurer; import org.springframework.http.codec.json.Jackson2JsonDecoder; import org.springframework.http.server.reactive.HttpHandler; import org.springframework.lang.Nullable; import org.springframework.test.web.reactive.server.HttpHandlerConnector; -import org.springframework.util.Assert; import org.springframework.util.MimeType; import org.springframework.web.reactive.function.client.WebClient; import org.springframework.web.reactive.function.server.HandlerStrategies; @@ -99,7 +92,7 @@ public class WebGraphQlClientBuilderTests { WebGraphQlClient client = builder.build(); client.document(DOCUMENT).execute().block(TIMEOUT); - WebGraphQlRequest request = builderSetup.getWebGraphQlRequest(); + WebGraphQlRequest request = builderSetup.getActualRequest(); assertThat(request.getUri().toString()).isEqualTo(url); assertThat(request.getHeaders().get("h")).containsExactly("one"); @@ -107,14 +100,14 @@ public class WebGraphQlClientBuilderTests { builder = client.mutate().headers(headers -> headers.add("h", "two")); client = builder.build(); client.document(DOCUMENT).execute().block(TIMEOUT); - assertThat(builderSetup.getWebGraphQlRequest().getHeaders().get("h")).containsExactly("one", "two"); + assertThat(builderSetup.getActualRequest().getHeaders().get("h")).containsExactly("one", "two"); // Mutate to replace header builder = client.mutate().header("h", "three", "four"); client = builder.build(); client.document(DOCUMENT).execute().block(TIMEOUT); - request = builderSetup.getWebGraphQlRequest(); + request = builderSetup.getActualRequest(); assertThat(request.getUri().toString()).isEqualTo(url); assertThat(request.getHeaders().get("h")).containsExactly("three", "four"); } @@ -129,7 +122,7 @@ public class WebGraphQlClientBuilderTests { HttpGraphQlClient client = builder.build(); client.document(DOCUMENT).execute().block(TIMEOUT); - assertThat(clientSetup.getWebGraphQlRequest().getHeaders().get("h")).containsExactly("one"); + assertThat(clientSetup.getActualRequest().getHeaders().get("h")).containsExactly("one"); // Mutate to add header value HttpGraphQlClient.Builder builder2 = client.mutate() @@ -137,7 +130,7 @@ public class WebGraphQlClientBuilderTests { client = builder2.build(); client.document(DOCUMENT).execute().block(TIMEOUT); - assertThat(clientSetup.getWebGraphQlRequest().getHeaders().get("h")).containsExactly("one", "two"); + assertThat(clientSetup.getActualRequest().getHeaders().get("h")).containsExactly("one", "two"); // Mutate to replace header HttpGraphQlClient.Builder builder3 = client.mutate() @@ -145,7 +138,7 @@ public class WebGraphQlClientBuilderTests { client = builder3.build(); client.document(DOCUMENT).execute().block(TIMEOUT); - assertThat(clientSetup.getWebGraphQlRequest().getHeaders().get("h")).containsExactly("three"); + assertThat(clientSetup.getActualRequest().getHeaders().get("h")).containsExactly("three"); } @ParameterizedTest @@ -160,14 +153,14 @@ public class WebGraphQlClientBuilderTests { WebGraphQlClient client = builder.build(); client.documentName("name").execute().block(TIMEOUT); - WebGraphQlRequest request = builderSetup.getWebGraphQlRequest(); + WebGraphQlRequest request = builderSetup.getActualRequest(); assertThat(request.getDocument()).isEqualTo(DOCUMENT); // Mutate client = client.mutate().build(); client.documentName("name").execute().block(TIMEOUT); - request = builderSetup.getWebGraphQlRequest(); + request = builderSetup.getActualRequest(); assertThat(request.getDocument()).isEqualTo(DOCUMENT); } @@ -178,7 +171,7 @@ public class WebGraphQlClientBuilderTests { WebGraphQlClient client = builderSetup.initBuilder().url("/graphql one").build(); client.document(DOCUMENT).execute().block(TIMEOUT); - assertThat(builderSetup.getWebGraphQlRequest().getUri().toString()).isEqualTo("/graphql%20one"); + assertThat(builderSetup.getActualRequest().getUri().toString()).isEqualTo("/graphql%20one"); } @ParameterizedTest @@ -192,7 +185,7 @@ public class WebGraphQlClientBuilderTests { String document = "{me {name}}"; MovieCharacter character = MovieCharacter.create("Luke Skywalker"); - builderSetup.setMockResponse(document, + builderSetup.getGraphQlService().setResponse(document, ExecutionResultImpl.newExecutionResult() .data(Collections.singletonMap("me", character)) .build()); @@ -211,12 +204,12 @@ public class WebGraphQlClientBuilderTests { private interface ClientBuilderSetup { + MockExecutionGraphQlService getGraphQlService(); + + WebGraphQlRequest getActualRequest(); + WebGraphQlClient.Builder initBuilder(); - void setMockResponse(String document, ExecutionResult result); - - WebGraphQlRequest getWebGraphQlRequest(); - } @@ -224,24 +217,24 @@ public class WebGraphQlClientBuilderTests { private WebGraphQlRequest graphQlRequest; - private final Map responses = new HashMap<>(); + private final MockExecutionGraphQlService graphQlService = new MockExecutionGraphQlService(); public AbstractBuilderSetup() { + this.graphQlService.setDefaultDataAsJson("{}"); + } - ExecutionGraphQlResponse defaultResponse = new DefaultExecutionGraphQlResponse( - ExecutionInput.newExecutionInput().query(DOCUMENT).build(), - ExecutionResultImpl.newExecutionResult().build()); + @Override + public MockExecutionGraphQlService getGraphQlService() { + return this.graphQlService; + } - this.responses.put(DOCUMENT, defaultResponse); + @Override + public WebGraphQlRequest getActualRequest() { + return this.graphQlRequest; } protected WebGraphQlHandler webGraphQlHandler() { - return WebGraphQlHandler.builder(request -> { - String document = request.getDocument(); - ExecutionGraphQlResponse response = this.responses.get(document); - Assert.notNull(response, "Unexpected request: " + document); - return Mono.just(response); - }) + return WebGraphQlHandler.builder(this.graphQlService) .interceptor((request, chain) -> { this.graphQlRequest = request; return chain.next(graphQlRequest); @@ -249,17 +242,6 @@ public class WebGraphQlClientBuilderTests { .build(); } - @Override - public void setMockResponse(String document, ExecutionResult result) { - ExecutionInput executionInput = ExecutionInput.newExecutionInput().query(document).build(); - this.responses.put(document, new DefaultExecutionGraphQlResponse(executionInput, result)); - } - - @Override - public WebGraphQlRequest getWebGraphQlRequest() { - return this.graphQlRequest; - } - } diff --git a/spring-graphql/src/test/java/org/springframework/graphql/client/WebSocketGraphQlTransportTests.java b/spring-graphql/src/test/java/org/springframework/graphql/client/WebSocketGraphQlTransportTests.java index 27e976fb..bd6371bc 100644 --- a/spring-graphql/src/test/java/org/springframework/graphql/client/WebSocketGraphQlTransportTests.java +++ b/spring-graphql/src/test/java/org/springframework/graphql/client/WebSocketGraphQlTransportTests.java @@ -35,8 +35,6 @@ import org.springframework.graphql.GraphQlRequest; import org.springframework.graphql.GraphQlResponse; import org.springframework.graphql.ResponseError; import org.springframework.graphql.support.DefaultGraphQlRequest; -import org.springframework.graphql.server.TestWebSocketClient; -import org.springframework.graphql.server.TestWebSocketConnection; import org.springframework.graphql.server.support.GraphQlWebSocketMessage; import org.springframework.graphql.server.support.GraphQlWebSocketMessageType; import org.springframework.http.HttpHeaders; diff --git a/spring-graphql/src/testFixtures/java/org/springframework/graphql/server/TestWebSocketClient.java b/spring-graphql/src/testFixtures/java/org/springframework/graphql/client/TestWebSocketClient.java similarity index 98% rename from spring-graphql/src/testFixtures/java/org/springframework/graphql/server/TestWebSocketClient.java rename to spring-graphql/src/testFixtures/java/org/springframework/graphql/client/TestWebSocketClient.java index b6717a69..41669b90 100644 --- a/spring-graphql/src/testFixtures/java/org/springframework/graphql/server/TestWebSocketClient.java +++ b/spring-graphql/src/testFixtures/java/org/springframework/graphql/client/TestWebSocketClient.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.springframework.graphql.server; +package org.springframework.graphql.client; import java.net.URI; import java.util.List; diff --git a/spring-graphql/src/testFixtures/java/org/springframework/graphql/server/TestWebSocketConnection.java b/spring-graphql/src/testFixtures/java/org/springframework/graphql/client/TestWebSocketConnection.java similarity index 99% rename from spring-graphql/src/testFixtures/java/org/springframework/graphql/server/TestWebSocketConnection.java rename to spring-graphql/src/testFixtures/java/org/springframework/graphql/client/TestWebSocketConnection.java index 44ffec84..7efbe021 100644 --- a/spring-graphql/src/testFixtures/java/org/springframework/graphql/server/TestWebSocketConnection.java +++ b/spring-graphql/src/testFixtures/java/org/springframework/graphql/client/TestWebSocketConnection.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.springframework.graphql.server; +package org.springframework.graphql.client; import java.net.URI; import java.util.ArrayList; diff --git a/spring-graphql/src/testFixtures/java/org/springframework/graphql/execution/MockExecutionGraphQlService.java b/spring-graphql/src/testFixtures/java/org/springframework/graphql/execution/MockExecutionGraphQlService.java new file mode 100644 index 00000000..8bc42a7a --- /dev/null +++ b/spring-graphql/src/testFixtures/java/org/springframework/graphql/execution/MockExecutionGraphQlService.java @@ -0,0 +1,151 @@ +/* + * Copyright 2002-2022 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.graphql.execution; + +import java.util.Arrays; +import java.util.HashMap; +import java.util.Map; +import java.util.function.Consumer; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import graphql.ExecutionInput; +import graphql.ExecutionResult; +import graphql.ExecutionResultImpl; +import graphql.GraphQLError; +import graphql.GraphqlErrorBuilder; +import reactor.core.publisher.Flux; +import reactor.core.publisher.Mono; + +import org.springframework.graphql.ExecutionGraphQlRequest; +import org.springframework.graphql.ExecutionGraphQlResponse; +import org.springframework.graphql.ExecutionGraphQlService; +import org.springframework.graphql.GraphQlRequest; +import org.springframework.graphql.GraphQlResponse; +import org.springframework.graphql.client.GraphQlTransport; +import org.springframework.graphql.support.DefaultExecutionGraphQlRequest; +import org.springframework.graphql.support.DefaultExecutionGraphQlResponse; +import org.springframework.lang.Nullable; +import org.springframework.util.Assert; +import org.springframework.util.ObjectUtils; + + +/** + * + * + * @author Rossen Stoyanchev + */ +public class MockExecutionGraphQlService implements ExecutionGraphQlService { + + private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper(); + + + private ExecutionGraphQlRequest graphQlRequest; + + private final Map responses = new HashMap<>(); + + @Nullable + private ExecutionGraphQlResponse defaultResponse; + + + public void setDefaultDataAsJson(String dataJson) { + ExecutionInput input = ExecutionInput.newExecutionInput().query("").build(); + ExecutionResult result = ExecutionResultImpl.newExecutionResult().data(decode(dataJson)).build(); + this.defaultResponse = new DefaultExecutionGraphQlResponse(input, result); + } + + public void setDataAsJson(String document, String dataJson) { + setResponse(document, decode(dataJson)); + } + + public void setErrors(String document, GraphQLError... errors) { + setResponse(document, null, errors); + } + + public void setError(String document, Consumer> errorBuilderConsumer) { + GraphqlErrorBuilder errorBuilder = GraphqlErrorBuilder.newError(); + errorBuilderConsumer.accept(errorBuilder); + setResponse(document, null, errorBuilder.build()); + } + + public void setDataAsJsonAndErrors(String document, String dataJson, GraphQLError... errors) { + setResponse(document, decode(dataJson), errors); + } + + private void setResponse(String document, @Nullable Map data, GraphQLError... errors) { + ExecutionResultImpl.Builder builder = new ExecutionResultImpl.Builder(); + if (data != null) { + builder.data(data); + } + if (!ObjectUtils.isEmpty(errors)) { + builder.errors(Arrays.asList(errors)); + } + setResponse(document, builder.build()); + } + + @SuppressWarnings("unused") + public void setResponse(String document, ExecutionResult result) { + ExecutionInput input = ExecutionInput.newExecutionInput().query(document).build(); + this.responses.put(document, new DefaultExecutionGraphQlResponse(input, result)); + } + + @SuppressWarnings("unchecked") + private Map decode(String json) { + try { + return OBJECT_MAPPER.readValue(json, Map.class); + } + catch (JsonProcessingException ex) { + throw new IllegalStateException(ex); + } + } + + public ExecutionGraphQlRequest getGraphQlRequest() { + return this.graphQlRequest; + } + + + @Override + public Mono execute(ExecutionGraphQlRequest request) { + this.graphQlRequest = request; + String document = request.getDocument(); + ExecutionGraphQlResponse response = this.responses.getOrDefault(document, this.defaultResponse); + Assert.notNull(response, "Unexpected request: " + document); + return Mono.just(response); + } + + public GraphQlTransport asGraphQlTransport() { + return new GraphQlTransport() { + + @Override + public Mono execute(GraphQlRequest request) { + ExecutionGraphQlRequest executionRequest = toExecutionRequest(request); + return MockExecutionGraphQlService.this.execute(executionRequest).cast(GraphQlResponse.class); + } + + @Override + public Flux executeSubscription(GraphQlRequest request) { + return Flux.error(new UnsupportedOperationException()); + } + }; + } + + private ExecutionGraphQlRequest toExecutionRequest(GraphQlRequest request) { + return new DefaultExecutionGraphQlRequest( + request.getDocument(), request.getOperationName(), request.getVariables(), "1", null); + } + +}