From 0b71596aa5c6cc1871d80f3e75d965f43284d25c Mon Sep 17 00:00:00 2001 From: Rossen Stoyanchev Date: Mon, 28 Jun 2021 07:12:19 +0100 Subject: [PATCH] Global error filter in GraphQlTester.Builder See gh-66 --- .../test/tester/DefaultGraphQlTester.java | 106 +++++++++++------- .../test/tester/DefaultWebGraphQlTester.java | 58 ++++++---- .../graphql/test/tester/GraphQlTester.java | 12 +- ...e.java => GraphQlTesterBuilderConfig.java} | 35 ++++-- .../graphql/test/tester/TestGraphQlError.java | 2 +- .../test/tester/GraphQlTesterTests.java | 47 +++++--- .../test/tester/WebGraphQlTesterTests.java | 32 +++++- 7 files changed, 200 insertions(+), 92 deletions(-) rename spring-graphql-test/src/main/java/org/springframework/graphql/test/tester/{BuilderDelegate.java => GraphQlTesterBuilderConfig.java} (70%) diff --git a/spring-graphql-test/src/main/java/org/springframework/graphql/test/tester/DefaultGraphQlTester.java b/spring-graphql-test/src/main/java/org/springframework/graphql/test/tester/DefaultGraphQlTester.java index c5465447..549084b3 100644 --- a/spring-graphql-test/src/main/java/org/springframework/graphql/test/tester/DefaultGraphQlTester.java +++ b/spring-graphql-test/src/main/java/org/springframework/graphql/test/tester/DefaultGraphQlTester.java @@ -59,8 +59,8 @@ class DefaultGraphQlTester implements GraphQlTester { private final RequestStrategy requestStrategy; - DefaultGraphQlTester(GraphQlService service, Configuration config, Duration responseTimeout) { - this(new GraphQlServiceRequestStrategy(service, config, responseTimeout)); + DefaultGraphQlTester(GraphQlService service, GraphQlTesterBuilderConfig builderConfig) { + this(new GraphQlServiceRequestStrategy(service, builderConfig)); } DefaultGraphQlTester(RequestStrategy requestStrategy) { @@ -86,29 +86,34 @@ class DefaultGraphQlTester implements GraphQlTester { private final GraphQlService service; - private final BuilderDelegate delegate = new BuilderDelegate(); + private final GraphQlTesterBuilderConfig builderConfig = new GraphQlTesterBuilderConfig(); DefaultBuilder(GraphQlService service) { Assert.notNull(service, "GraphQlService is required."); this.service = service; } + @Override + public DefaultBuilder errorFilter(Predicate predicate) { + this.builderConfig.errorFilter(predicate); + return this; + } + @Override public DefaultBuilder jsonPathConfig(Configuration config) { - this.delegate.jsonPathConfig(config); + this.builderConfig.jsonPathConfig(config); return this; } @Override public DefaultBuilder responseTimeout(Duration timeout) { - this.delegate.responseTimeout(timeout); + this.builderConfig.responseTimeout(timeout); return this; } @Override public GraphQlTester build() { - return new DefaultGraphQlTester( - this.service, this.delegate.initJsonPathConfig(), this.delegate.getResponseTimeout()); + return new DefaultGraphQlTester(this.service, this.builderConfig); } } @@ -141,24 +146,30 @@ class DefaultGraphQlTester implements GraphQlTester { */ protected abstract static class AbstractDirectRequestStrategy implements RequestStrategy { - private final Configuration jsonPathConfig; + private final GraphQlTesterBuilderConfig builderConfig; - private final Duration responseTimeout; - - protected AbstractDirectRequestStrategy(Configuration jsonPathConfig, Duration responseTimeout) { - this.jsonPathConfig = jsonPathConfig; - this.responseTimeout = responseTimeout; + protected AbstractDirectRequestStrategy(GraphQlTesterBuilderConfig builderConfig) { + this.builderConfig = builderConfig; } - protected Duration getResponseTimeout() { - return this.responseTimeout; + @Nullable + private Predicate errorFilter() { + return this.builderConfig.getErrorFilter(); + } + + private Configuration jsonPathConfig() { + return this.builderConfig.getJsonPathConfig(); + } + + protected Duration responseTimeout() { + return this.builderConfig.getResponseTimeout(); } @Override public ResponseSpec execute(RequestInput input) { ExecutionResult executionResult = executeInternal(input); - DocumentContext context = JsonPath.parse(executionResult.toSpecification(), this.jsonPathConfig); - return new DefaultResponseSpec(context, assertDecorator(input)); + DocumentContext context = JsonPath.parse(executionResult.toSpecification(), jsonPathConfig()); + return new DefaultResponseSpec(context, errorFilter(), assertDecorator(input)); } @Override @@ -171,7 +182,7 @@ class DefaultGraphQlTester implements GraphQlTester { assertDecorator.accept(() -> AssertionErrors.assertTrue( "Response has " + errors.size() + " unexpected error(s).", CollectionUtils.isEmpty(errors))); - return new DefaultSubscriptionSpec(result.getData(), this.jsonPathConfig, assertDecorator); + return new DefaultSubscriptionSpec(result.getData(), errorFilter(), jsonPathConfig(), assertDecorator); } /** @@ -199,17 +210,15 @@ class DefaultGraphQlTester implements GraphQlTester { private final GraphQlService graphQlService; - protected GraphQlServiceRequestStrategy( - GraphQlService service, Configuration jsonPathConfig, Duration responseTimeout) { - - super(jsonPathConfig, responseTimeout); + protected GraphQlServiceRequestStrategy(GraphQlService service, GraphQlTesterBuilderConfig builderConfig) { + super(builderConfig); Assert.notNull(service, "GraphQlService is required."); this.graphQlService = service; } protected ExecutionResult executeInternal(RequestInput input) { ExecutionInput executionInput = input.toExecutionInput(); - ExecutionResult result = this.graphQlService.execute(executionInput).block(getResponseTimeout()); + ExecutionResult result = this.graphQlService.execute(executionInput).block(responseTimeout()); Assert.notNull(result, "Expected ExecutionResult"); return result; } @@ -324,19 +333,28 @@ class DefaultGraphQlTester implements GraphQlTester { private final Consumer assertDecorator; - ErrorsContainer(List errors, Consumer assertDecorator) { + ErrorsContainer( + List errors, @Nullable Predicate errorFilter, + Consumer assertDecorator) { + Assert.notNull(errors, "`errors` is required"); Assert.notNull(assertDecorator, "`assertDecorator` is required"); this.errors = errors; this.assertDecorator = assertDecorator; + filterErrors(errorFilter); } void doAssert(Runnable task) { this.assertDecorator.accept(task); } - void filterErrors(Predicate errorPredicate) { - this.errors.forEach((error) -> error.filter(errorPredicate)); + void filterErrors(@Nullable Predicate predicate) { + if (predicate != null) { + this.errors.forEach((error) -> { + // Error marked "filtered" if true + error.applyErrorFilterPredicate(predicate); + }); + } } void consumeErrors(Consumer> consumer) { @@ -345,8 +363,8 @@ class DefaultGraphQlTester implements GraphQlTester { } void verifyErrors() { - - List unexpected = this.errors.stream().filter((error) -> !error.isExpected()) + List unexpected = this.errors.stream() + .filter(error -> !error.isExpected()) .collect(Collectors.toList()); this.assertDecorator @@ -366,14 +384,19 @@ class DefaultGraphQlTester implements GraphQlTester { */ private static class ResponseContainer extends ErrorsContainer { + private static final TypeRef> ERROR_LIST_TYPE = new TypeRef>() {}; + private static final JsonPath ERRORS_PATH = JsonPath.compile("$.errors"); private final DocumentContext documentContext; private final String jsonContent; - ResponseContainer(DocumentContext documentContext, Consumer assertDecorator) { - super(readErrors(documentContext), assertDecorator); + ResponseContainer( + DocumentContext documentContext, @Nullable Predicate errorFilter, + Consumer assertDecorator) { + + super(readErrors(documentContext), errorFilter, assertDecorator); this.documentContext = documentContext; this.jsonContent = this.documentContext.jsonString(); } @@ -381,8 +404,7 @@ class DefaultGraphQlTester implements GraphQlTester { private static List readErrors(DocumentContext documentContext) { Assert.notNull(documentContext, "DocumentContext is required"); try { - return documentContext.read(ERRORS_PATH, new TypeRef>() { - }); + return documentContext.read(ERRORS_PATH, ERROR_LIST_TYPE); } catch (PathNotFoundException ex) { return Collections.emptyList(); @@ -419,11 +441,14 @@ class DefaultGraphQlTester implements GraphQlTester { /** * Class constructor. * @param documentContext the parsed response content + * @param errorFilter a globally defined filter for expected errors (to be ignored) * @param assertDecorator decorator to apply around assertions, e.g. to add extra - * contextual information such as HTTP request and response body details */ - protected DefaultResponseSpec(DocumentContext documentContext, Consumer assertDecorator) { - this.responseContainer = new ResponseContainer(documentContext, assertDecorator); + protected DefaultResponseSpec( + DocumentContext documentContext, @Nullable Predicate errorFilter, + Consumer assertDecorator) { + + this.responseContainer = new ResponseContainer(documentContext, errorFilter, assertDecorator); } @Override @@ -755,14 +780,19 @@ class DefaultGraphQlTester implements GraphQlTester { private final Publisher publisher; + @Nullable + private final Predicate errorFilter; + private final Configuration jsonPathConfig; private final Consumer assertDecorator; - protected DefaultSubscriptionSpec(Publisher publisher, Configuration jsonPathConfig, - Consumer decorator) { + protected DefaultSubscriptionSpec( + Publisher publisher, @Nullable Predicate errorFilter, + Configuration jsonPathConfig, Consumer decorator) { this.publisher = publisher; + this.errorFilter = errorFilter; this.jsonPathConfig = jsonPathConfig; this.assertDecorator = decorator; } @@ -771,7 +801,7 @@ class DefaultGraphQlTester implements GraphQlTester { public Flux toFlux() { return Flux.from(this.publisher).map((result) -> { DocumentContext context = JsonPath.parse(result.toSpecification(), this.jsonPathConfig); - return new DefaultResponseSpec(context, this.assertDecorator); + return new DefaultResponseSpec(context, this.errorFilter, this.assertDecorator); }); } diff --git a/spring-graphql-test/src/main/java/org/springframework/graphql/test/tester/DefaultWebGraphQlTester.java b/spring-graphql-test/src/main/java/org/springframework/graphql/test/tester/DefaultWebGraphQlTester.java index 71d6e29d..3df80149 100644 --- a/spring-graphql-test/src/main/java/org/springframework/graphql/test/tester/DefaultWebGraphQlTester.java +++ b/spring-graphql-test/src/main/java/org/springframework/graphql/test/tester/DefaultWebGraphQlTester.java @@ -20,12 +20,14 @@ import java.net.URI; import java.nio.charset.StandardCharsets; import java.time.Duration; import java.util.function.Consumer; +import java.util.function.Predicate; import java.util.function.Supplier; import com.jayway.jsonpath.Configuration; import com.jayway.jsonpath.DocumentContext; import com.jayway.jsonpath.JsonPath; import graphql.ExecutionResult; +import graphql.GraphQLError; import org.springframework.graphql.RequestInput; import org.springframework.graphql.web.WebGraphQlHandler; @@ -69,34 +71,38 @@ class DefaultWebGraphQlTester extends DefaultGraphQlTester implements WebGraphQl private final Supplier requestStrategySupplier; - private final BuilderDelegate delegate = new BuilderDelegate(); + private final GraphQlTesterBuilderConfig builderConfig = new GraphQlTesterBuilderConfig(); @Nullable private HttpHeaders headers; DefaultBuilder(WebTestClient client) { - this.requestStrategySupplier = () -> - new WebTestClientRequestStrategy( - client.mutate().responseTimeout(this.delegate.getResponseTimeout()).build(), - this.delegate.initJsonPathConfig()); + this.requestStrategySupplier = () -> { + Duration timeout = this.builderConfig.getResponseTimeout(); + WebTestClient clientToUse = client.mutate().responseTimeout(timeout).build(); + return new WebTestClientRequestStrategy(clientToUse, this.builderConfig); + }; } DefaultBuilder(WebGraphQlHandler handler) { - this.requestStrategySupplier = () -> - new WebGraphQlHandlerRequestStrategy(handler, - this.delegate.initJsonPathConfig(), - this.delegate.getResponseTimeout()); + this.requestStrategySupplier = () -> new WebGraphQlHandlerRequestStrategy(handler, this.builderConfig); + } + + @Override + public WebGraphQlTester.Builder errorFilter(Predicate predicate) { + this.builderConfig.errorFilter(predicate); + return this; } @Override public DefaultBuilder jsonPathConfig(Configuration config) { - this.delegate.jsonPathConfig(config); + this.builderConfig.jsonPathConfig(config); return this; } @Override public DefaultBuilder responseTimeout(Duration timeout) { - this.delegate.responseTimeout(timeout); + this.builderConfig.responseTimeout(timeout); return this; } @@ -131,11 +137,20 @@ class DefaultWebGraphQlTester extends DefaultGraphQlTester implements WebGraphQl private final WebTestClient client; - private final Configuration jsonPathConfig; + private final GraphQlTesterBuilderConfig builderConfig; - WebTestClientRequestStrategy(WebTestClient client, Configuration jsonPathConfig) { + WebTestClientRequestStrategy(WebTestClient client, GraphQlTesterBuilderConfig builderConfig) { this.client = client; - this.jsonPathConfig = jsonPathConfig; + this.builderConfig = builderConfig; + } + + @Nullable + private Predicate errorFilter() { + return this.builderConfig.getErrorFilter(); + } + + private Configuration jsonPathConfig() { + return this.builderConfig.getJsonPathConfig(); } @Override @@ -155,9 +170,9 @@ class DefaultWebGraphQlTester extends DefaultGraphQlTester implements WebGraphQl byte[] bytes = result.getResponseBodyContent(); Assert.notNull(bytes, "Expected GraphQL response content"); String content = new String(bytes, StandardCharsets.UTF_8); - DocumentContext documentContext = JsonPath.parse(content, this.jsonPathConfig); + DocumentContext documentContext = JsonPath.parse(content, jsonPathConfig()); - return new DefaultResponseSpec(documentContext, result::assertWithDiagnostics); + return new DefaultResponseSpec(documentContext, errorFilter(), result::assertWithDiagnostics); } @Override @@ -174,8 +189,9 @@ class DefaultWebGraphQlTester extends DefaultGraphQlTester implements WebGraphQl .contentType(MediaType.TEXT_EVENT_STREAM) .returnResult(TestExecutionResult.class); - return new DefaultSubscriptionSpec(exchangeResult.getResponseBody().cast(ExecutionResult.class), - this.jsonPathConfig, exchangeResult::assertWithDiagnostics); + return new DefaultSubscriptionSpec( + exchangeResult.getResponseBody().cast(ExecutionResult.class), + errorFilter(), jsonPathConfig(), exchangeResult::assertWithDiagnostics); } private HttpHeaders getHeaders(RequestInput requestInput) { @@ -193,15 +209,15 @@ class DefaultWebGraphQlTester extends DefaultGraphQlTester implements WebGraphQl private final WebGraphQlHandler graphQlHandler; - WebGraphQlHandlerRequestStrategy(WebGraphQlHandler handler, Configuration config, Duration responseTimeout) { - super(config, responseTimeout); + WebGraphQlHandlerRequestStrategy(WebGraphQlHandler handler, GraphQlTesterBuilderConfig builderConfig) { + super(builderConfig); this.graphQlHandler = handler; } protected ExecutionResult executeInternal(RequestInput input) { Assert.isInstanceOf(WebInput.class, input); WebInput webInput = (WebInput) input; - ExecutionResult result = this.graphQlHandler.handle(webInput).block(getResponseTimeout()); + ExecutionResult result = this.graphQlHandler.handle(webInput).block(responseTimeout()); Assert.notNull(result, "Expected ExecutionResult"); return result; } diff --git a/spring-graphql-test/src/main/java/org/springframework/graphql/test/tester/GraphQlTester.java b/spring-graphql-test/src/main/java/org/springframework/graphql/test/tester/GraphQlTester.java index f87efe0b..af73acf4 100644 --- a/spring-graphql-test/src/main/java/org/springframework/graphql/test/tester/GraphQlTester.java +++ b/spring-graphql-test/src/main/java/org/springframework/graphql/test/tester/GraphQlTester.java @@ -78,6 +78,16 @@ public interface GraphQlTester { */ interface Builder> { + /** + * Add a global filter for expected errors. All errors that match the + * given predicate are treated as expected and ignored on + * {@link GraphQlTester.ErrorSpec#verify()} or when + * {@link TraverseSpec#path(String) traversing} to a data path. + * @param predicate the error filter to add + * @return the same builder instance + */ + T errorFilter(Predicate predicate); + /** * Provide JSONPath configuration settings, including a * {@link com.jayway.jsonpath.spi.json.JsonProvider} as well as a @@ -424,7 +434,7 @@ public interface GraphQlTester { * Add a filter for expected errors. All errors that match the predicate are * treated as expected and ignored on {@link #verify()} or when * {@link TraverseSpec#path(String) traversing} to a data path. - * @param errorPredicate the predicate to add + * @param errorPredicate the error filter to add * @return the same spec to add more filters before {@link #verify()} */ ErrorSpec filter(Predicate errorPredicate); diff --git a/spring-graphql-test/src/main/java/org/springframework/graphql/test/tester/BuilderDelegate.java b/spring-graphql-test/src/main/java/org/springframework/graphql/test/tester/GraphQlTesterBuilderConfig.java similarity index 70% rename from spring-graphql-test/src/main/java/org/springframework/graphql/test/tester/BuilderDelegate.java rename to spring-graphql-test/src/main/java/org/springframework/graphql/test/tester/GraphQlTesterBuilderConfig.java index ae1d0947..055f0c13 100644 --- a/spring-graphql-test/src/main/java/org/springframework/graphql/test/tester/BuilderDelegate.java +++ b/spring-graphql-test/src/main/java/org/springframework/graphql/test/tester/GraphQlTesterBuilderConfig.java @@ -16,22 +16,25 @@ package org.springframework.graphql.test.tester; import java.time.Duration; +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 graphql.GraphQLError; import org.springframework.lang.Nullable; import org.springframework.util.Assert; import org.springframework.util.ClassUtils; /** - * Assist with collecting the input for {@link GraphQlTester.Builder}, - * essentially to avoid challenges with generics in the builder hierarchy. + * Holds the input required for {@link GraphQlTester.Builder}, providing a + * convenient way to pass it together, while also helping to avoid challenges + * with builder hierarchy generics. * * @author Rossen Stoyanchev */ -final class BuilderDelegate { +final class GraphQlTesterBuilderConfig { private static final boolean jackson2Present; @@ -42,11 +45,18 @@ final class BuilderDelegate { } + @Nullable + private Predicate errorFilter; + @Nullable private Configuration jsonPathConfig; private Duration responseTimeout = Duration.ofSeconds(5); + public void errorFilter(Predicate predicate) { + this.errorFilter = (this.errorFilter != null ? errorFilter.and(predicate) : predicate); + } + public void jsonPathConfig(@Nullable Configuration config) { this.jsonPathConfig = config; } @@ -56,16 +66,17 @@ final class BuilderDelegate { this.responseTimeout = timeout; } - public Configuration initJsonPathConfig() { - if (this.jsonPathConfig != null) { - return this.jsonPathConfig; - } - else if (jackson2Present) { - return Jackson2Configuration.create(); - } - else { - return Configuration.builder().build(); + @Nullable + public Predicate getErrorFilter() { + return this.errorFilter; + } + + public Configuration getJsonPathConfig() { + if (this.jsonPathConfig == null) { + this.jsonPathConfig = (jackson2Present ? + Jackson2Configuration.create() : Configuration.builder().build()); } + return this.jsonPathConfig; } public Duration getResponseTimeout() { diff --git a/spring-graphql-test/src/main/java/org/springframework/graphql/test/tester/TestGraphQlError.java b/spring-graphql-test/src/main/java/org/springframework/graphql/test/tester/TestGraphQlError.java index a0acf243..85c613f7 100644 --- a/spring-graphql-test/src/main/java/org/springframework/graphql/test/tester/TestGraphQlError.java +++ b/spring-graphql-test/src/main/java/org/springframework/graphql/test/tester/TestGraphQlError.java @@ -121,7 +121,7 @@ class TestGraphQlError implements GraphQLError { * Mark this error as expected if it matches the predicate. * @param predicate the error predicate */ - void filter(Predicate predicate) { + void applyErrorFilterPredicate(Predicate predicate) { this.expected |= predicate.test(this); } 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 abd04385..9add8c3b 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 @@ -60,10 +60,10 @@ public class GraphQlTesterTests { private final GraphQlService service = mock(GraphQlService.class); - private final ArgumentCaptor inputCaptor = ArgumentCaptor.forClass(ExecutionInput.class); - private final GraphQlTester graphQlTester = GraphQlTester.create(this.service); + private final ArgumentCaptor inputCaptor = ArgumentCaptor.forClass(ExecutionInput.class); + @Test void pathAndValueExistsAndEmptyChecks() throws Exception { @@ -77,7 +77,7 @@ public class GraphQlTesterTests { spec.path("me.friends").valueIsEmpty(); spec.path("hero").pathDoesNotExist().valueDoesNotExist().valueIsEmpty(); - assertThat(getActualQuery()).contains(query); + assertThat(this.inputCaptor.getValue().getQuery()).contains(query); } @Test @@ -97,7 +97,7 @@ public class GraphQlTesterTests { .as("Extended fields should fail in strict mode") .hasMessageContaining("Unexpected: name"); - assertThat(getActualQuery()).contains(query); + assertThat(this.inputCaptor.getValue().getQuery()).contains(query); } @Test @@ -127,7 +127,7 @@ public class GraphQlTesterTests { .entity(new ParameterizedTypeReference>() {}) .isEqualTo(Collections.singletonMap("me", luke)); - assertThat(getActualQuery()).contains(query); + assertThat(this.inputCaptor.getValue().getQuery()).contains(query); } @Test @@ -163,7 +163,7 @@ public class GraphQlTesterTests { .entityList(new ParameterizedTypeReference() {}) .containsExactly(han, leia); - assertThat(getActualQuery()).contains(query); + assertThat(this.inputCaptor.getValue().getQuery()).contains(query); } @Test @@ -202,7 +202,7 @@ public class GraphQlTesterTests { assertThatThrownBy(() -> this.graphQlTester.query(query).executeAndVerify()) .hasMessageContaining("Response has 1 unexpected error(s)."); - assertThat(getActualQuery()).contains(query); + assertThat(this.inputCaptor.getValue().getQuery()).contains(query); } @Test @@ -214,7 +214,7 @@ public class GraphQlTesterTests { assertThatThrownBy(() -> this.graphQlTester.query(query).execute().path("me")) .hasMessageContaining("Response has 1 unexpected error(s)."); - assertThat(getActualQuery()).contains(query); + assertThat(this.inputCaptor.getValue().getQuery()).contains(query); } @Test @@ -233,7 +233,7 @@ public class GraphQlTesterTests { .verify()) .hasMessageContaining("Response has 1 unexpected error(s) of 2 total."); - assertThat(getActualQuery()).contains(query); + assertThat(this.inputCaptor.getValue().getQuery()).contains(query); } @Test @@ -252,7 +252,28 @@ public class GraphQlTesterTests { .path("me") .pathDoesNotExist(); - assertThat(getActualQuery()).contains(query); + assertThat(this.inputCaptor.getValue().getQuery()).contains(query); + } + + @Test + void errorsFilteredGlobally() throws Exception { + + String query = "{me {name, friends}}"; + setResponse( + GraphqlErrorBuilder.newError().message("some error").build(), + GraphqlErrorBuilder.newError().message("some other error").build()); + + GraphQlTester.builder(this.service) + .errorFilter((error) -> error.getMessage().startsWith("some ")) + .build() + .query(query) + .execute() + .errors() + .verify() + .path("me") + .pathDoesNotExist(); + + assertThat(this.inputCaptor.getValue().getQuery()).contains(query); } @Test @@ -277,7 +298,7 @@ public class GraphQlTesterTests { .path("me") .pathDoesNotExist(); - assertThat(getActualQuery()).contains(query); + assertThat(this.inputCaptor.getValue().getQuery()).contains(query); } private void setResponse(String data) throws Exception { @@ -300,8 +321,4 @@ public class GraphQlTesterTests { given(this.service.execute(this.inputCaptor.capture())).willReturn(Mono.just(result)); } - private String getActualQuery() { - return this.inputCaptor.getValue().getQuery(); - } - } diff --git a/spring-graphql-test/src/test/java/org/springframework/graphql/test/tester/WebGraphQlTesterTests.java b/spring-graphql-test/src/test/java/org/springframework/graphql/test/tester/WebGraphQlTesterTests.java index 6db338de..982a92ed 100644 --- a/spring-graphql-test/src/test/java/org/springframework/graphql/test/tester/WebGraphQlTesterTests.java +++ b/spring-graphql-test/src/test/java/org/springframework/graphql/test/tester/WebGraphQlTesterTests.java @@ -29,9 +29,11 @@ import com.fasterxml.jackson.databind.ObjectMapper; import graphql.ExecutionResult; import graphql.ExecutionResultImpl; import graphql.GraphQLError; +import graphql.GraphqlErrorBuilder; import okhttp3.mockwebserver.MockResponse; import okhttp3.mockwebserver.MockWebServer; import okhttp3.mockwebserver.RecordedRequest; +import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.MethodSource; import org.mockito.ArgumentCaptor; @@ -60,8 +62,9 @@ import static org.mockito.Mockito.mock; * * *

- * There is no actual handling via {@link graphql.GraphQL} in either scenario. The main - * focus is to verify {@link GraphQlTester} request preparation and response handling. + * There is no actual handling via {@link graphql.GraphQL} in either scenario. + * The main focus is to verify {@link GraphQlTester} request preparation and + * response handling. */ public class WebGraphQlTesterTests { @@ -121,6 +124,28 @@ public class WebGraphQlTesterTests { setup.shutdown(); } + @ParameterizedTest + @MethodSource("argumentSource") + void errorsFilteredGlobally(GraphQlTesterSetup setup) throws Exception { + + String query = "{me {name, friends}}"; + setup.response( + GraphqlErrorBuilder.newError().message("some error").build(), + GraphqlErrorBuilder.newError().message("some other error").build()); + + setup.graphQlTesterBuilder() + .errorFilter((error) -> error.getMessage().startsWith("some ")) + .build() + .query(query) + .execute() + .errors() + .verify() + .path("me") + .pathDoesNotExist(); + + setup.verifyRequest((input) -> assertThat(input.getQuery()).contains(query)); + } + private interface GraphQlTesterSetup { @@ -243,8 +268,7 @@ public class WebGraphQlTesterTests { public void response(@Nullable String data, List errors) throws Exception { ExecutionResultImpl.Builder builder = new ExecutionResultImpl.Builder(); if (data != null) { - builder.data(OBJECT_MAPPER.readValue(data, new TypeReference>() { - })); + builder.data(OBJECT_MAPPER.readValue(data, new TypeReference>() {})); } if (!CollectionUtils.isEmpty(errors)) { builder.addErrors(errors);