Inline RequestSpecDelegate in DefaultGraphQlTester

The delegate has almost no logic, simply holding fields and calling the
RequestStrategy, so it adds cognitive overhead without benefit.
This commit is contained in:
Rossen Stoyanchev
2021-09-30 14:39:21 +01:00
parent 6975e6c37b
commit f0f883cc39
2 changed files with 49 additions and 77 deletions

View File

@@ -114,9 +114,9 @@ class DefaultGraphQlTester implements GraphQlTester {
public GraphQlTester build() { public GraphQlTester build() {
return new DefaultGraphQlTester(this.service, this.builderConfig); return new DefaultGraphQlTester(this.service, this.builderConfig);
} }
} }
/** /**
* Internal strategy abstracting how a GraphQL request is performed. * Internal strategy abstracting how a GraphQL request is performed.
*/ */
@@ -138,6 +138,7 @@ class DefaultGraphQlTester implements GraphQlTester {
} }
/** /**
* Base class for a {@link RequestStrategy} that perform GraphQL requests * Base class for a {@link RequestStrategy} that perform GraphQL requests
* without an underlying transport and where {@link RequestInput} provides * without an underlying transport and where {@link RequestInput} provides
@@ -199,9 +200,9 @@ class DefaultGraphQlTester implements GraphQlTester {
} }
}; };
} }
} }
/** /**
* {@link RequestStrategy} that performs requests through a {@link GraphQlService}. * {@link RequestStrategy} that performs requests through a {@link GraphQlService}.
*/ */
@@ -222,11 +223,11 @@ class DefaultGraphQlTester implements GraphQlTester {
} }
} }
/** /**
* Assist with collecting the input for {@link GraphQlTester.RequestSpec}, * {@link RequestSpec} that collects the query, operationName, and variables.
* helping to avoid challenges with generics in the builder hierarchy.
*/ */
final static class RequestSpecDelegate { static class DefaultRequestSpec implements RequestSpec<DefaultRequestSpec> {
private final RequestStrategy requestStrategy; private final RequestStrategy requestStrategy;
@@ -237,92 +238,46 @@ class DefaultGraphQlTester implements GraphQlTester {
private final Map<String, Object> variables = new LinkedHashMap<>(); private final Map<String, Object> variables = new LinkedHashMap<>();
protected RequestSpecDelegate(RequestStrategy requestStrategy, String query) { protected DefaultRequestSpec(RequestStrategy requestStrategy, String query) {
Assert.notNull(requestStrategy, "RequestStrategy is required"); Assert.notNull(requestStrategy, "RequestStrategy is required");
Assert.notNull(query, "`query` is required"); Assert.notNull(query, "`query` is required");
this.requestStrategy = requestStrategy; this.requestStrategy = requestStrategy;
this.query = query; this.query = query;
} }
public void operationName(@Nullable String name) {
this.operationName = name;
}
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<DefaultRequestSpec> {
private final RequestSpecDelegate delegate;
protected DefaultRequestSpec(RequestStrategy requestStrategy, String query) {
this.delegate = new RequestSpecDelegate(requestStrategy, query);
}
@Override @Override
public DefaultRequestSpec operationName(@Nullable String name) { public DefaultRequestSpec operationName(@Nullable String name) {
this.delegate.operationName(name); this.operationName = name;
return this; return this;
} }
@Override @Override
public DefaultRequestSpec variable(String name, Object value) { public DefaultRequestSpec variable(String name, Object value) {
this.delegate.variable(name, value); this.variables.put(name, value);
return this; return this;
} }
@Override @Override
public ResponseSpec execute() { public ResponseSpec execute() {
return this.delegate.execute(); return this.requestStrategy.execute(createRequestInput());
} }
@Override @Override
public void executeAndVerify() { public void executeAndVerify() {
this.delegate.executeAndVerify(); execute().path("$.errors").valueIsEmpty();
} }
@Override @Override
public SubscriptionSpec executeSubscription() { public SubscriptionSpec executeSubscription() {
return this.delegate.executeSubscription(); return this.requestStrategy.executeSubscription(createRequestInput());
} }
public RequestInput createRequestInput() {
return new RequestInput(this.query, this.operationName, this.variables);
}
} }
private static class ErrorsContainer { private static class ErrorsContainer {
private static final Predicate<GraphQLError> MATCH_ALL_PREDICATE = (error) -> true; private static final Predicate<GraphQLError> MATCH_ALL_PREDICATE = (error) -> true;
@@ -374,9 +329,9 @@ class DefaultGraphQlTester implements GraphQlTester {
+ unexpected, + unexpected,
CollectionUtils.isEmpty(unexpected))); CollectionUtils.isEmpty(unexpected)));
} }
} }
/** /**
* Container for a GraphQL response with access to data and errors. * Container for a GraphQL response with access to data and errors.
*/ */
@@ -426,9 +381,9 @@ class DefaultGraphQlTester implements GraphQlTester {
<T> T read(JsonPath jsonPath, TypeRef<T> typeRef) { <T> T read(JsonPath jsonPath, TypeRef<T> typeRef) {
return this.documentContext.read(jsonPath, typeRef); return this.documentContext.read(jsonPath, typeRef);
} }
} }
/** /**
* {@link ResponseSpec} that operates on the response from a GraphQL HTTP request. * {@link ResponseSpec} that operates on the response from a GraphQL HTTP request.
*/ */
@@ -614,9 +569,9 @@ class DefaultGraphQlTester implements GraphQlTester {
} }
}); });
} }
} }
/** /**
* {@link EntitySpec} implementation. * {@link EntitySpec} implementation.
*/ */
@@ -697,9 +652,9 @@ class DefaultGraphQlTester implements GraphQlTester {
private <T extends S> T self() { private <T extends S> T self() {
return (T) this; return (T) this;
} }
} }
/** /**
* {@link ListEntitySpec} implementation. * {@link ListEntitySpec} implementation.
*/ */
@@ -767,9 +722,9 @@ class DefaultGraphQlTester implements GraphQlTester {
(getEntity() != null && getEntity().size() > boundary))); (getEntity() != null && getEntity().size() > boundary)));
return this; return this;
} }
} }
/** /**
* {@link SubscriptionSpec} implementation that operates on a {@link Publisher} of * {@link SubscriptionSpec} implementation that operates on a {@link Publisher} of
* {@link ExecutionResult}. * {@link ExecutionResult}.
@@ -802,7 +757,6 @@ class DefaultGraphQlTester implements GraphQlTester {
return new DefaultResponseSpec(context, this.errorFilter, this.assertDecorator); return new DefaultResponseSpec(context, this.errorFilter, this.assertDecorator);
}); });
} }
} }
} }

View File

@@ -19,6 +19,8 @@ package org.springframework.graphql.test.tester;
import java.net.URI; import java.net.URI;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
import java.time.Duration; import java.time.Duration;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.function.Consumer; import java.util.function.Consumer;
import java.util.function.Predicate; import java.util.function.Predicate;
import java.util.function.Supplier; import java.util.function.Supplier;
@@ -228,12 +230,22 @@ class DefaultWebGraphQlTester extends DefaultGraphQlTester implements WebGraphQl
private static final URI DEFAULT_URL = URI.create(""); private static final URI DEFAULT_URL = URI.create("");
private final RequestSpecDelegate delegate; private final RequestStrategy requestStrategy;
private final String query;
@Nullable
private String operationName;
private final Map<String, Object> variables = new LinkedHashMap<>();
private final HttpHeaders headers = new HttpHeaders(); private final HttpHeaders headers = new HttpHeaders();
DefaultWebRequestSpec(RequestStrategy requestStrategy, String query, @Nullable HttpHeaders headers) { DefaultWebRequestSpec(RequestStrategy requestStrategy, String query, @Nullable HttpHeaders headers) {
this.delegate = new RequestSpecDelegate(requestStrategy, query); Assert.notNull(requestStrategy, "RequestStrategy is required");
Assert.notNull(query, "`query` is required");
this.requestStrategy = requestStrategy;
this.query = query;
if (!CollectionUtils.isEmpty(headers)) { if (!CollectionUtils.isEmpty(headers)) {
this.headers.putAll(headers); this.headers.putAll(headers);
} }
@@ -255,36 +267,42 @@ class DefaultWebGraphQlTester extends DefaultGraphQlTester implements WebGraphQl
@Override @Override
public WebRequestSpec operationName(@Nullable String name) { public WebRequestSpec operationName(@Nullable String name) {
this.delegate.operationName(name); this.operationName = name;
return this; return this;
} }
@Override @Override
public WebRequestSpec variable(String name, Object value) { public WebRequestSpec variable(String name, Object value) {
this.delegate.variable(name, value); this.variables.put(name, value);
return this; return this;
} }
@Override @Override
public ResponseSpec execute() { public ResponseSpec execute() {
return this.delegate.execute(createRequestInput()); return this.requestStrategy.execute(createRequestInput());
} }
@Override @Override
public void executeAndVerify() { public void executeAndVerify() {
this.delegate.executeAndVerify(createRequestInput()); execute().path("$.errors").valueIsEmpty();
} }
@Override @Override
public SubscriptionSpec executeSubscription() { public SubscriptionSpec executeSubscription() {
return this.delegate.executeSubscription(createRequestInput()); return this.requestStrategy.executeSubscription(createRequestInput());
} }
private RequestInput createRequestInput() { private RequestInput createRequestInput() {
RequestInput requestInput = this.delegate.createRequestInput(); Map<String, Object> body = new LinkedHashMap<>(3);
return new WebInput(DEFAULT_URL, this.headers, requestInput.toMap(), null); body.put("query", this.query);
if (this.operationName != null) {
body.put("operationName", this.operationName);
}
if (!CollectionUtils.isEmpty(this.variables)) {
body.put("variables", new LinkedHashMap<>(this.variables));
}
return new WebInput(DEFAULT_URL, this.headers, body, null);
} }
} }
} }