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 d74821e0..c5465447 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 @@ -74,7 +74,7 @@ class DefaultGraphQlTester implements GraphQlTester { @Override - public RequestSpec query(String query) { + public RequestSpec query(String query) { return new DefaultRequestSpec(this.requestStrategy, query); } @@ -216,9 +216,10 @@ class DefaultGraphQlTester implements GraphQlTester { } /** - * {@link RequestSpec} that collects the query, operationName, and variables. + * Assist with collecting the input for {@link GraphQlTester.RequestSpec}, + * helping to avoid challenges with generics in the builder hierarchy. */ - protected static class DefaultRequestSpec implements RequestSpec { + final static class RequestSpecDelegate { private final RequestStrategy requestStrategy; @@ -229,52 +230,88 @@ class DefaultGraphQlTester implements GraphQlTester { private final Map variables = new LinkedHashMap<>(); - protected DefaultRequestSpec(RequestStrategy requestStrategy, String query) { + protected RequestSpecDelegate(RequestStrategy requestStrategy, String query) { Assert.notNull(requestStrategy, "RequestStrategy is required"); Assert.notNull(query, "`query` is required"); this.requestStrategy = requestStrategy; this.query = query; } - @Override - public RequestSpec operationName(@Nullable String name) { + public void operationName(@Nullable String name) { this.operationName = name; - return this; } - @Override - public RequestSpec variable(String name, Object value) { + public void variable(String name, Object value) { this.variables.put(name, value); + } + + public ResponseSpec execute() { + return execute(createRequestInput()); + } + + public ResponseSpec execute(RequestInput input) { + return this.requestStrategy.execute(input); + } + + public void executeAndVerify() { + executeAndVerify(createRequestInput()); + } + + public void executeAndVerify(RequestInput input) { + ResponseSpec spec = this.requestStrategy.execute(input); + spec.path("$.errors").valueIsEmpty(); + } + + public SubscriptionSpec executeSubscription() { + return executeSubscription(createRequestInput()); + } + + public SubscriptionSpec executeSubscription(RequestInput input) { + return this.requestStrategy.executeSubscription(input); + } + + public RequestInput createRequestInput() { + return new RequestInput(this.query, this.operationName, this.variables); + } + + } + + /** + * {@link RequestSpec} that collects the query, operationName, and variables. + */ + static class DefaultRequestSpec implements RequestSpec { + + private final RequestSpecDelegate delegate; + + protected DefaultRequestSpec(RequestStrategy requestStrategy, String query) { + this.delegate = new RequestSpecDelegate(requestStrategy, query); + } + + @Override + public DefaultRequestSpec operationName(@Nullable String name) { + this.delegate.operationName(name); return this; } @Override - public RequestSpec variables(Consumer> variablesConsumer) { - variablesConsumer.accept(this.variables); + public DefaultRequestSpec variable(String name, Object value) { + this.delegate.variable(name, value); return this; } @Override public ResponseSpec execute() { - RequestInput input = createRequestInput(); - return this.requestStrategy.execute(input); + return this.delegate.execute(); } @Override public void executeAndVerify() { - RequestInput input = createRequestInput(); - ResponseSpec spec = this.requestStrategy.execute(input); - spec.path("$.errors").valueIsEmpty(); + this.delegate.executeAndVerify(); } @Override public SubscriptionSpec executeSubscription() { - RequestInput input = createRequestInput(); - return this.requestStrategy.executeSubscription(input); - } - - protected RequestInput createRequestInput() { - return new RequestInput(this.query, this.operationName, this.variables); + return this.delegate.executeSubscription(); } } 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 a3fde271..71d6e29d 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 @@ -208,14 +208,16 @@ class DefaultWebGraphQlTester extends DefaultGraphQlTester implements WebGraphQl } - private static final class DefaultWebRequestSpec extends DefaultRequestSpec implements WebRequestSpec { + private static final class DefaultWebRequestSpec implements WebRequestSpec { private static final URI DEFAULT_URL = URI.create(""); + private final RequestSpecDelegate delegate; + private final HttpHeaders headers = new HttpHeaders(); DefaultWebRequestSpec(RequestStrategy requestStrategy, String query, @Nullable HttpHeaders headers) { - super(requestStrategy, query); + this.delegate = new RequestSpecDelegate(requestStrategy, query); if (!CollectionUtils.isEmpty(headers)) { this.headers.putAll(headers); } @@ -236,8 +238,34 @@ class DefaultWebGraphQlTester extends DefaultGraphQlTester implements WebGraphQl } @Override - protected RequestInput createRequestInput() { - RequestInput requestInput = super.createRequestInput(); + public WebRequestSpec operationName(@Nullable String name) { + this.delegate.operationName(name); + return this; + } + + @Override + public WebRequestSpec variable(String name, Object value) { + this.delegate.variable(name, value); + return this; + } + + @Override + public ResponseSpec execute() { + return this.delegate.execute(createRequestInput()); + } + + @Override + public void executeAndVerify() { + this.delegate.executeAndVerify(createRequestInput()); + } + + @Override + public SubscriptionSpec executeSubscription() { + return this.delegate.executeSubscription(createRequestInput()); + } + + private RequestInput createRequestInput() { + RequestInput requestInput = this.delegate.createRequestInput(); return new WebInput(DEFAULT_URL, this.headers, requestInput.toMap(), null); } 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 5a662d31..f87efe0b 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 @@ -137,14 +137,14 @@ public interface GraphQlTester { /** * Declare options to gather input for a GraphQL request and execute it. */ - interface RequestSpec extends ExecuteSpec { + interface RequestSpec> extends ExecuteSpec { /** * Set the operation name. * @param name the operation name * @return this request spec */ - RequestSpec operationName(@Nullable String name); + T operationName(@Nullable String name); /** * Add a variable. @@ -152,14 +152,7 @@ public interface GraphQlTester { * @param value the variable value * @return this request spec */ - RequestSpec variable(String name, Object value); - - /** - * Modify variables by accessing the underlying map. - * @param variablesConsumer a callback for the map of variables - * @return this request spec - */ - RequestSpec variables(Consumer> variablesConsumer); + T variable(String name, Object value); } diff --git a/spring-graphql-test/src/main/java/org/springframework/graphql/test/tester/WebGraphQlTester.java b/spring-graphql-test/src/main/java/org/springframework/graphql/test/tester/WebGraphQlTester.java index f4e58590..24230426 100644 --- a/spring-graphql-test/src/main/java/org/springframework/graphql/test/tester/WebGraphQlTester.java +++ b/spring-graphql-test/src/main/java/org/springframework/graphql/test/tester/WebGraphQlTester.java @@ -162,7 +162,7 @@ public interface WebGraphQlTester extends GraphQlTester { * Extends {@link GraphQlTester.RequestSpec} with further input options * applicable to Web requests. */ - interface WebRequestSpec extends RequestSpec { + interface WebRequestSpec extends RequestSpec { /** * Add the given, single header value under the given name. 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 96a99874..abd04385 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 @@ -180,7 +180,7 @@ public class GraphQlTesterTests { GraphQlTester.ResponseSpec spec = this.graphQlTester.query(query) .operationName("HeroNameAndFriends") .variable("episode", "JEDI") - .variables((map) -> map.put("foo", "bar")) + .variable("foo", "bar") .execute(); spec.path("hero").entity(MovieCharacter.class).isEqualTo(MovieCharacter.create("R2-D2"));