From ed8c27923fa938fa1049feaa9b88025cb223dcc9 Mon Sep 17 00:00:00 2001 From: rstoyanchev Date: Mon, 16 May 2022 09:50:36 +0100 Subject: [PATCH] Fix cyclic dependencies and polishing --- .../RSocketGraphQlTesterBuilderTests.java | 2 +- .../tester/WebGraphQlTesterBuilderTests.java | 5 +- .../execution/ThreadLocalAccessor.java | 5 +- .../client/GraphQlClientTestSupport.java | 37 +++++++++- .../RSocketGraphQlClientBuilderTests.java | 2 +- .../client/WebGraphQlClientBuilderTests.java | 5 +- .../MockExecutionGraphQlService.java | 67 +++++++++---------- 7 files changed, 81 insertions(+), 42 deletions(-) diff --git a/spring-graphql-test/src/test/java/org/springframework/graphql/test/tester/RSocketGraphQlTesterBuilderTests.java b/spring-graphql-test/src/test/java/org/springframework/graphql/test/tester/RSocketGraphQlTesterBuilderTests.java index 70616185..53d61550 100644 --- a/spring-graphql-test/src/test/java/org/springframework/graphql/test/tester/RSocketGraphQlTesterBuilderTests.java +++ b/spring-graphql-test/src/test/java/org/springframework/graphql/test/tester/RSocketGraphQlTesterBuilderTests.java @@ -126,7 +126,7 @@ public class RSocketGraphQlTesterBuilderTests { private Closeable server; public BuilderSetup() { - this.graphQlService.setDefaultDataAsJson("{}"); + this.graphQlService.setDefaultResponse("{}"); } public RSocketGraphQlTester.Builder initBuilder() { 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 3f9f84de..d2340015 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 @@ -45,6 +45,7 @@ import org.springframework.http.codec.ClientCodecConfigurer; import org.springframework.http.codec.json.Jackson2JsonDecoder; import org.springframework.lang.Nullable; import org.springframework.test.web.reactive.server.WebTestClient; +import org.springframework.util.Assert; import org.springframework.util.MimeType; import org.springframework.web.reactive.function.server.RouterFunction; import org.springframework.web.reactive.function.server.ServerResponse; @@ -205,12 +206,13 @@ public class WebGraphQlTesterBuilderTests { private static class WebBuilderSetup implements TesterBuilderSetup { + @Nullable private WebGraphQlRequest request; private final MockExecutionGraphQlService graphQlService = new MockExecutionGraphQlService(); public WebBuilderSetup() { - this.graphQlService.setDefaultDataAsJson("{}"); + this.graphQlService.setDefaultResponse("{}"); } @Override @@ -234,6 +236,7 @@ public class WebGraphQlTesterBuilderTests { @Override public WebGraphQlRequest getWebGraphQlRequest() { + Assert.state(this.request != null, "No saved WebGraphQlRequest"); return this.request; } diff --git a/spring-graphql/src/main/java/org/springframework/graphql/execution/ThreadLocalAccessor.java b/spring-graphql/src/main/java/org/springframework/graphql/execution/ThreadLocalAccessor.java index 5482270e..f6617949 100644 --- a/spring-graphql/src/main/java/org/springframework/graphql/execution/ThreadLocalAccessor.java +++ b/spring-graphql/src/main/java/org/springframework/graphql/execution/ThreadLocalAccessor.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2021 the original author or authors. + * Copyright 2002-2022 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -20,7 +20,6 @@ import java.util.List; import java.util.Map; import org.springframework.beans.factory.ObjectProvider; -import org.springframework.graphql.server.WebGraphQlHandler; /** * Interface to be implemented to assist with the extraction of ThreadLocal @@ -38,7 +37,7 @@ import org.springframework.graphql.server.WebGraphQlHandler; * * @author Rossen Stoyanchev * @since 1.0.0 - * @see WebGraphQlHandler.Builder#threadLocalAccessor(ThreadLocalAccessor...) + * @see org.springframework.graphql.server.WebGraphQlHandler.Builder#threadLocalAccessor(ThreadLocalAccessor...) */ public interface ThreadLocalAccessor { diff --git a/spring-graphql/src/test/java/org/springframework/graphql/client/GraphQlClientTestSupport.java b/spring-graphql/src/test/java/org/springframework/graphql/client/GraphQlClientTestSupport.java index 23778178..9c017363 100644 --- a/spring-graphql/src/test/java/org/springframework/graphql/client/GraphQlClientTestSupport.java +++ b/spring-graphql/src/test/java/org/springframework/graphql/client/GraphQlClientTestSupport.java @@ -18,8 +18,14 @@ package org.springframework.graphql.client; import java.time.Duration; +import reactor.core.publisher.Flux; +import reactor.core.publisher.Mono; + +import org.springframework.graphql.ExecutionGraphQlService; import org.springframework.graphql.GraphQlRequest; +import org.springframework.graphql.GraphQlResponse; import org.springframework.graphql.execution.MockExecutionGraphQlService; +import org.springframework.graphql.support.DefaultExecutionGraphQlRequest; /** * Base class for {@link GraphQlClient} tests. @@ -32,7 +38,7 @@ public class GraphQlClientTestSupport { private final MockExecutionGraphQlService graphQlService = new MockExecutionGraphQlService(); - private final GraphQlClient.Builder clientBuilder = GraphQlClient.builder(this.graphQlService.asGraphQlTransport()); + private final GraphQlClient.Builder clientBuilder = GraphQlClient.builder(new MockTransport(this.graphQlService)); private final GraphQlClient client = this.clientBuilder.build(); @@ -53,4 +59,33 @@ public class GraphQlClientTestSupport { return this.graphQlService.getGraphQlRequest(); } + + private static class MockTransport implements GraphQlTransport { + + private final ExecutionGraphQlService graphQlService; + + private MockTransport(ExecutionGraphQlService graphQlService) { + this.graphQlService = graphQlService; + } + + @Override + public Mono execute(GraphQlRequest request) { + return graphQlService.execute( + new DefaultExecutionGraphQlRequest( + request.getDocument(), + request.getOperationName(), + request.getVariables(), + request.getExtensions(), + "1", + null)) + .cast(GraphQlResponse.class); + } + + @Override + public Flux executeSubscription(GraphQlRequest request) { + return Flux.error(new UnsupportedOperationException()); + } + + } + } diff --git a/spring-graphql/src/test/java/org/springframework/graphql/client/RSocketGraphQlClientBuilderTests.java b/spring-graphql/src/test/java/org/springframework/graphql/client/RSocketGraphQlClientBuilderTests.java index 69be8fd9..93df372a 100644 --- a/spring-graphql/src/test/java/org/springframework/graphql/client/RSocketGraphQlClientBuilderTests.java +++ b/spring-graphql/src/test/java/org/springframework/graphql/client/RSocketGraphQlClientBuilderTests.java @@ -94,7 +94,7 @@ public class RSocketGraphQlClientBuilderTests { private Closeable server; public BuilderSetup() { - this.graphQlService.setDefaultDataAsJson("{}"); + this.graphQlService.setDefaultResponse("{}"); } public MockExecutionGraphQlService getGraphQlService() { diff --git a/spring-graphql/src/test/java/org/springframework/graphql/client/WebGraphQlClientBuilderTests.java b/spring-graphql/src/test/java/org/springframework/graphql/client/WebGraphQlClientBuilderTests.java index 1f2c480b..447f3532 100644 --- a/spring-graphql/src/test/java/org/springframework/graphql/client/WebGraphQlClientBuilderTests.java +++ b/spring-graphql/src/test/java/org/springframework/graphql/client/WebGraphQlClientBuilderTests.java @@ -45,6 +45,7 @@ import org.springframework.http.codec.json.Jackson2JsonDecoder; import org.springframework.http.server.reactive.HttpHandler; import org.springframework.lang.Nullable; import org.springframework.test.web.reactive.server.HttpHandlerConnector; +import org.springframework.util.Assert; import org.springframework.util.MimeType; import org.springframework.web.reactive.function.client.WebClient; import org.springframework.web.reactive.function.server.HandlerStrategies; @@ -239,12 +240,13 @@ public class WebGraphQlClientBuilderTests { private abstract static class AbstractBuilderSetup implements ClientBuilderSetup { + @Nullable private WebGraphQlRequest graphQlRequest; private final MockExecutionGraphQlService graphQlService = new MockExecutionGraphQlService(); public AbstractBuilderSetup() { - this.graphQlService.setDefaultDataAsJson("{}"); + this.graphQlService.setDefaultResponse("{}"); } @Override @@ -254,6 +256,7 @@ public class WebGraphQlClientBuilderTests { @Override public WebGraphQlRequest getActualRequest() { + Assert.state(this.graphQlRequest != null, "No saved WebGraphQlRequest"); return this.graphQlRequest; } diff --git a/spring-graphql/src/testFixtures/java/org/springframework/graphql/execution/MockExecutionGraphQlService.java b/spring-graphql/src/testFixtures/java/org/springframework/graphql/execution/MockExecutionGraphQlService.java index 7126a54c..e8e11ee9 100644 --- a/spring-graphql/src/testFixtures/java/org/springframework/graphql/execution/MockExecutionGraphQlService.java +++ b/spring-graphql/src/testFixtures/java/org/springframework/graphql/execution/MockExecutionGraphQlService.java @@ -28,24 +28,18 @@ import graphql.ExecutionResult; import graphql.ExecutionResultImpl; import graphql.GraphQLError; import graphql.GraphqlErrorBuilder; -import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; import org.springframework.graphql.ExecutionGraphQlRequest; import org.springframework.graphql.ExecutionGraphQlResponse; import org.springframework.graphql.ExecutionGraphQlService; -import org.springframework.graphql.GraphQlRequest; -import org.springframework.graphql.GraphQlResponse; -import org.springframework.graphql.client.GraphQlTransport; -import org.springframework.graphql.support.DefaultExecutionGraphQlRequest; import org.springframework.graphql.support.DefaultExecutionGraphQlResponse; import org.springframework.lang.Nullable; import org.springframework.util.Assert; import org.springframework.util.ObjectUtils; - /** - * + * {@link ExecutionGraphQlService} with mock responses. * * @author Rossen Stoyanchev */ @@ -54,6 +48,7 @@ public class MockExecutionGraphQlService implements ExecutionGraphQlService { private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper(); + @Nullable private ExecutionGraphQlRequest graphQlRequest; private final Map responses = new HashMap<>(); @@ -62,30 +57,57 @@ public class MockExecutionGraphQlService implements ExecutionGraphQlService { private ExecutionGraphQlResponse defaultResponse; - public void setDefaultDataAsJson(String dataJson) { + /** + * Get the last, saved request. + */ + public ExecutionGraphQlRequest getGraphQlRequest() { + Assert.state(this.graphQlRequest != null, "No saved GraphQlRequest"); + return this.graphQlRequest; + } + + + /** + * Set the default response to fall back on as a "data"-only response. + */ + public void setDefaultResponse(String dataJson) { ExecutionInput input = ExecutionInput.newExecutionInput().query("").build(); ExecutionResult result = ExecutionResultImpl.newExecutionResult().data(decode(dataJson)).build(); this.defaultResponse = new DefaultExecutionGraphQlResponse(input, result); } + /** + * Set a "data"-only response for the given document. + */ public void setDataAsJson(String document, String dataJson) { setResponse(document, decode(dataJson)); } + /** + * Set an "errors" response for the given document. + */ public void setErrors(String document, GraphQLError... errors) { setResponse(document, null, errors); } + /** + * Set an "errors" response for the given document. + */ public void setError(String document, Consumer> errorBuilderConsumer) { GraphqlErrorBuilder errorBuilder = GraphqlErrorBuilder.newError(); errorBuilderConsumer.accept(errorBuilder); setResponse(document, null, errorBuilder.build()); } + /** + * Set a "data" and "errors" response for the given document. + */ public void setDataAsJsonAndErrors(String document, String dataJson, GraphQLError... errors) { setResponse(document, decode(dataJson), errors); } + /** + * Set a "data" and "errors" response for the given document. + */ private void setResponse(String document, @Nullable Map data, GraphQLError... errors) { ExecutionResultImpl.Builder builder = new ExecutionResultImpl.Builder(); if (data != null) { @@ -97,6 +119,9 @@ public class MockExecutionGraphQlService implements ExecutionGraphQlService { setResponse(document, builder.build()); } + /** + * Set a response for the given document. + */ @SuppressWarnings("unused") public void setResponse(String document, ExecutionResult result) { ExecutionInput input = ExecutionInput.newExecutionInput().query(document).build(); @@ -113,11 +138,6 @@ public class MockExecutionGraphQlService implements ExecutionGraphQlService { } } - public ExecutionGraphQlRequest getGraphQlRequest() { - return this.graphQlRequest; - } - - @Override public Mono execute(ExecutionGraphQlRequest request) { this.graphQlRequest = request; @@ -127,25 +147,4 @@ public class MockExecutionGraphQlService implements ExecutionGraphQlService { return Mono.just(response); } - public GraphQlTransport asGraphQlTransport() { - return new GraphQlTransport() { - - @Override - public Mono execute(GraphQlRequest request) { - ExecutionGraphQlRequest executionRequest = toExecutionRequest(request); - return MockExecutionGraphQlService.this.execute(executionRequest).cast(GraphQlResponse.class); - } - - @Override - public Flux executeSubscription(GraphQlRequest request) { - return Flux.error(new UnsupportedOperationException()); - } - }; - } - - private ExecutionGraphQlRequest toExecutionRequest(GraphQlRequest request) { - return new DefaultExecutionGraphQlRequest( - request.getDocument(), request.getOperationName(), request.getVariables(), request.getExtensions(), "1", null); - } - }