From f6b9fdfe7c0c61f1434616f0970b110fa3109055 Mon Sep 17 00:00:00 2001 From: rstoyanchev Date: Wed, 9 Mar 2022 12:13:52 +0000 Subject: [PATCH] Fix issue with matchesJson when JSONPath is a String GraphQlTransport returns ExecutionResult with parsed JSON so for the most part having MappingProvider is enough. However, when a JSONPath evaluates to String (vs Map or List), the JsonSmartJsonProvider used by default, throws UnsupportedOperationException from toJson. --- .../tester/AbstractGraphQlTesterBuilder.java | 27 ++++++++++++++++--- .../test/tester/GraphQlTesterTests.java | 3 +-- .../tester/WebGraphQlTesterBuilderTests.java | 1 + .../client/AbstractGraphQlClientBuilder.java | 13 ++++++--- 4 files changed, 36 insertions(+), 8 deletions(-) diff --git a/spring-graphql-test/src/main/java/org/springframework/graphql/test/tester/AbstractGraphQlTesterBuilder.java b/spring-graphql-test/src/main/java/org/springframework/graphql/test/tester/AbstractGraphQlTesterBuilder.java index 9f68512c..85316663 100644 --- a/spring-graphql-test/src/main/java/org/springframework/graphql/test/tester/AbstractGraphQlTesterBuilder.java +++ b/spring-graphql-test/src/main/java/org/springframework/graphql/test/tester/AbstractGraphQlTesterBuilder.java @@ -21,6 +21,7 @@ import java.util.function.Function; import java.util.function.Predicate; import com.jayway.jsonpath.Configuration; +import com.jayway.jsonpath.spi.json.JacksonJsonProvider; import com.jayway.jsonpath.spi.mapper.JacksonMappingProvider; import com.jayway.jsonpath.spi.mapper.MappingProvider; import graphql.GraphQLError; @@ -133,11 +134,31 @@ public abstract class AbstractGraphQlTesterBuilder defaultJsonProviderType; + + private static final Class defaultMappingProviderType; + + static { + Configuration config = Configuration.defaultConfiguration(); + defaultJsonProviderType = config.jsonProvider().getClass(); + defaultMappingProviderType = config.mappingProvider().getClass(); + } + + // GraphQlTransport returns ExecutionResult with JSON parsed to Map/List, + // but we still need JsonProvider for matchesJson(String) static Configuration configure(Configuration config) { - return (config.mappingProvider() != null && config.mappingProvider() != defaultProvider ? config : - config.mappingProvider(new JacksonMappingProvider())); + if (isDefault(config.jsonProvider(), defaultJsonProviderType)) { + config = config.jsonProvider(new JacksonJsonProvider()); + } + if (isDefault(config.mappingProvider(), defaultMappingProviderType)) { + config = config.mappingProvider(new JacksonMappingProvider()); + } + return config; + } + + private static boolean isDefault(@Nullable T provider, Class defaultProviderType) { + return (provider == null || defaultProviderType.isInstance(provider)); } } 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 d5a2a865..fd2728b8 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 @@ -82,8 +82,7 @@ public class GraphQlTesterTests extends GraphQlTesterTestSupport { response.path("").matchesJson("{\"me\": {\"name\":\"Luke Skywalker\",\"friends\":[]}}"); response.path("me").matchesJson("{\"name\":\"Luke Skywalker\"}"); - response.path("me").matchesJson("{\"friends\":[]}"); // lenient match with subset of - // fields + response.path("me").matchesJson("{\"friends\":[]}"); // lenient match with subset of fields assertThatThrownBy(() -> response.path("me").matchesJsonStrictly("{\"friends\":[]}")) .as("Extended fields should fail in strict mode") 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 fb3dcac4..33fa63fc 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 @@ -190,6 +190,7 @@ public class WebGraphQlTesterBuilderTests { assertThat(response).isNotNull(); response.path("me").entity(MovieCharacter.class).isEqualTo(character); + response.path("me").matchesJson("{name:\"Luke Skywalker\"}"); assertThat(testDecoder.getLastValue()).isEqualTo(character); } diff --git a/spring-graphql/src/main/java/org/springframework/graphql/client/AbstractGraphQlClientBuilder.java b/spring-graphql/src/main/java/org/springframework/graphql/client/AbstractGraphQlClientBuilder.java index da0e2484..b45de9b8 100644 --- a/spring-graphql/src/main/java/org/springframework/graphql/client/AbstractGraphQlClientBuilder.java +++ b/spring-graphql/src/main/java/org/springframework/graphql/client/AbstractGraphQlClientBuilder.java @@ -112,11 +112,18 @@ public abstract class AbstractGraphQlClientBuilder defaultMappingProviderType = + Configuration.defaultConfiguration().mappingProvider().getClass(); + + // We only need a MappingProvider: + // GraphQlTransport returns ExecutionResult with JSON parsed to Map/List static Configuration configure(Configuration config) { - return (config.mappingProvider() != null && config.mappingProvider() != defaultProvider ? config : - config.mappingProvider(new JacksonMappingProvider())); + MappingProvider provider = config.mappingProvider(); + if (provider == null || defaultMappingProviderType.isInstance(provider)) { + config = config.mappingProvider(new JacksonMappingProvider()); + } + return config; } }