diff --git a/spring-graphql-test/src/main/java/org/springframework/graphql/test/tester/DefaultExecutionGraphQlServiceTesterBuilder.java b/spring-graphql-test/src/main/java/org/springframework/graphql/test/tester/DefaultExecutionGraphQlServiceTesterBuilder.java index c59c8a7d..0033a7bd 100644 --- a/spring-graphql-test/src/main/java/org/springframework/graphql/test/tester/DefaultExecutionGraphQlServiceTesterBuilder.java +++ b/spring-graphql-test/src/main/java/org/springframework/graphql/test/tester/DefaultExecutionGraphQlServiceTesterBuilder.java @@ -17,9 +17,13 @@ package org.springframework.graphql.test.tester; +import java.util.Collections; import java.util.function.Consumer; +import org.springframework.core.codec.Decoder; +import org.springframework.core.codec.Encoder; import org.springframework.graphql.ExecutionGraphQlService; +import org.springframework.lang.Nullable; import org.springframework.util.Assert; @@ -36,6 +40,12 @@ final class DefaultExecutionGraphQlServiceTesterBuilder private final ExecutionGraphQlService service; + @Nullable + private Encoder encoder; + + @Nullable + private Decoder decoder; + DefaultExecutionGraphQlServiceTesterBuilder(ExecutionGraphQlService service) { Assert.notNull(service, "GraphQlService is required"); @@ -46,14 +56,36 @@ final class DefaultExecutionGraphQlServiceTesterBuilder this.service = transport.getGraphQlService(); } + @Override + public DefaultExecutionGraphQlServiceTesterBuilder encoder(Encoder encoder) { + this.encoder = encoder; + return this; + } + + @Override + public DefaultExecutionGraphQlServiceTesterBuilder decoder(Decoder decoder) { + this.decoder = decoder; + return this; + } @Override public ExecutionGraphQlServiceTester build() { + registerJsonPathMappingProvider(); GraphQlServiceGraphQlTransport transport = new GraphQlServiceGraphQlTransport(this.service); GraphQlTester tester = super.buildGraphQlTester(transport); return new DefaultExecutionGraphQlServiceTester(tester, transport, getBuilderInitializer()); } + private void registerJsonPathMappingProvider() { + if (this.encoder != null && this.decoder != null) { + configureJsonPathConfig(config -> { + EncoderDecoderMappingProvider provider = new EncoderDecoderMappingProvider( + Collections.singletonList(this.encoder), Collections.singletonList(this.decoder)); + return config.mappingProvider(provider); + }); + } + } + /** * Default {@link ExecutionGraphQlServiceTester} implementation. diff --git a/spring-graphql-test/src/main/java/org/springframework/graphql/test/tester/ExecutionGraphQlServiceTester.java b/spring-graphql-test/src/main/java/org/springframework/graphql/test/tester/ExecutionGraphQlServiceTester.java index bde96744..f1924f58 100644 --- a/spring-graphql-test/src/main/java/org/springframework/graphql/test/tester/ExecutionGraphQlServiceTester.java +++ b/spring-graphql-test/src/main/java/org/springframework/graphql/test/tester/ExecutionGraphQlServiceTester.java @@ -16,6 +16,8 @@ package org.springframework.graphql.test.tester; +import org.springframework.core.codec.Decoder; +import org.springframework.core.codec.Encoder; import org.springframework.graphql.ExecutionGraphQlService; /** @@ -52,6 +54,18 @@ public interface ExecutionGraphQlServiceTester extends GraphQlTester { */ interface Builder> extends GraphQlTester.Builder { + /** + * Configure the JSON encoder to use for mapping response data to + * higher level objects. + */ + B encoder(Encoder encoder); + + /** + * Configure the JSON decoder to use for mapping response data to + * higher level objects. + */ + B decoder(Decoder decoder); + /** * Build a {@link ExecutionGraphQlServiceTester} instance. */ 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 dc289e0b..31de0ab1 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 @@ -16,12 +16,23 @@ package org.springframework.graphql.test.tester; +import java.util.Collections; +import java.util.Map; + +import graphql.ExecutionResultImpl; import graphql.GraphqlErrorBuilder; import org.junit.jupiter.api.Test; 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.ExecutionGraphQlService; import org.springframework.graphql.support.DocumentSource; +import org.springframework.http.codec.json.Jackson2JsonDecoder; +import org.springframework.http.codec.json.Jackson2JsonEncoder; +import org.springframework.lang.Nullable; +import org.springframework.util.MimeType; import static org.assertj.core.api.Assertions.assertThat; @@ -65,6 +76,34 @@ public class GraphQlTesterBuilderTests extends GraphQlTesterTestSupport { assertThat(getActualRequestDocument()).isEqualTo(DOCUMENT); } + @Test + void codecConfigurerRegistersJsonPathMappingProvider() { + + TestJackson2JsonDecoder testDecoder = new TestJackson2JsonDecoder(); + + ExecutionGraphQlServiceTester.Builder builder = graphQlTesterBuilder() + .encoder(new Jackson2JsonEncoder()) + .decoder(testDecoder); + + String document = "{me {name}}"; + MovieCharacter character = MovieCharacter.create("Luke Skywalker"); + getGraphQlService().setResponse(document, + ExecutionResultImpl.newExecutionResult() + .data(Collections.singletonMap("me", character)) + .build()); + + GraphQlTester client = builder.build(); + GraphQlTester.Response response = client.document(document).execute(); + + testDecoder.resetLastValue(); + assertThat(testDecoder.getLastValue()).isNull(); + + assertThat(response).isNotNull(); + response.path("me").entity(MovieCharacter.class).isEqualTo(character); + response.path("me").matchesJson("{name:\"Luke Skywalker\"}"); + assertThat(testDecoder.getLastValue()).isEqualTo(character); + } + @Test void errorsFilteredGlobally() { @@ -86,4 +125,29 @@ public class GraphQlTesterBuilderTests extends GraphQlTesterTestSupport { assertThat(getActualRequestDocument()).contains(document); } + + private static class TestJackson2JsonDecoder extends Jackson2JsonDecoder { + + @Nullable + private Object lastValue; + + @Nullable + Object getLastValue() { + return this.lastValue; + } + + @Override + public Object decode(DataBuffer dataBuffer, ResolvableType targetType, + @Nullable MimeType mimeType, @Nullable Map hints) throws DecodingException { + + this.lastValue = super.decode(dataBuffer, targetType, mimeType, hints); + return this.lastValue; + } + + void resetLastValue() { + this.lastValue = null; + } + + } + } 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 71412728..020734c7 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 @@ -28,7 +28,8 @@ public class GraphQlTesterTestSupport { private final MockExecutionGraphQlService graphQlService = new MockExecutionGraphQlService(); - private final GraphQlTester.Builder graphQlTesterBuilder = ExecutionGraphQlServiceTester.builder(this.graphQlService); + private final ExecutionGraphQlServiceTester.Builder graphQlTesterBuilder = + ExecutionGraphQlServiceTester.builder(this.graphQlService); private final GraphQlTester graphQlTester = this.graphQlTesterBuilder.build(); @@ -45,7 +46,7 @@ public class GraphQlTesterTestSupport { return this.graphQlTester; } - public GraphQlTester.Builder graphQlTesterBuilder() { + public ExecutionGraphQlServiceTester.Builder graphQlTesterBuilder() { return this.graphQlTesterBuilder; }