From c9556035ca36a75dd2e3af8c3795464487b7285d Mon Sep 17 00:00:00 2001 From: Brian Clozel Date: Fri, 19 Apr 2024 15:34:07 +0200 Subject: [PATCH] Configure interceptors on WebSocketGraphQlTester This commit adds two new methods on the `WebSocketGraphQlTester` builder to configure `GraphQlClientInterceptor` instances on the client. For now, this is only accessible on the WebSocket tester but could be promoted to a higher level builder in the future. Closes gh-823 --- .../DefaultWebSocketGraphQlTesterBuilder.java | 22 +++++- .../test/tester/WebSocketGraphQlTester.java | 20 +++++ .../tester/WebSocketGraphQlTesterTests.java | 76 +++++++++++++++++++ 3 files changed, 116 insertions(+), 2 deletions(-) create mode 100644 spring-graphql-test/src/test/java/org/springframework/graphql/test/tester/WebSocketGraphQlTesterTests.java diff --git a/spring-graphql-test/src/main/java/org/springframework/graphql/test/tester/DefaultWebSocketGraphQlTesterBuilder.java b/spring-graphql-test/src/main/java/org/springframework/graphql/test/tester/DefaultWebSocketGraphQlTesterBuilder.java index 8a63390b..4a1928a6 100644 --- a/spring-graphql-test/src/main/java/org/springframework/graphql/test/tester/DefaultWebSocketGraphQlTesterBuilder.java +++ b/spring-graphql-test/src/main/java/org/springframework/graphql/test/tester/DefaultWebSocketGraphQlTesterBuilder.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2022 the original author or authors. + * Copyright 2002-2024 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. @@ -18,10 +18,14 @@ package org.springframework.graphql.test.tester; import java.net.URI; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; import java.util.function.Consumer; import reactor.core.publisher.Mono; +import org.springframework.graphql.client.GraphQlClientInterceptor; import org.springframework.graphql.client.WebSocketGraphQlClient; import org.springframework.http.HttpHeaders; import org.springframework.http.codec.CodecConfigurer; @@ -41,6 +45,8 @@ final class DefaultWebSocketGraphQlTesterBuilder private final WebSocketGraphQlClient.Builder graphQlClientBuilder; + private final List interceptors = new ArrayList<>(); + /** * Constructor to start via {@link WebSocketGraphQlTester#builder(String, WebSocketClient)}. @@ -98,10 +104,22 @@ final class DefaultWebSocketGraphQlTesterBuilder return this; } + @Override + public DefaultWebSocketGraphQlTesterBuilder interceptor(GraphQlClientInterceptor... interceptors) { + this.interceptors.addAll(Arrays.asList(interceptors)); + return this; + } + + @Override + public DefaultWebSocketGraphQlTesterBuilder interceptors(Consumer> interceptorsConsumer) { + interceptorsConsumer.accept(this.interceptors); + return this; + } + @Override public WebSocketGraphQlTester build() { registerJsonPathMappingProvider(); - WebSocketGraphQlClient client = this.graphQlClientBuilder.build(); + WebSocketGraphQlClient client = this.graphQlClientBuilder.interceptors((list) -> list.addAll(this.interceptors)).build(); GraphQlTester graphQlTester = super.buildGraphQlTester(asTransport(client)); return new DefaultWebSocketGraphQlTester(graphQlTester, client, getBuilderInitializer()); } diff --git a/spring-graphql-test/src/main/java/org/springframework/graphql/test/tester/WebSocketGraphQlTester.java b/spring-graphql-test/src/main/java/org/springframework/graphql/test/tester/WebSocketGraphQlTester.java index 86eeed93..ede03160 100644 --- a/spring-graphql-test/src/main/java/org/springframework/graphql/test/tester/WebSocketGraphQlTester.java +++ b/spring-graphql-test/src/main/java/org/springframework/graphql/test/tester/WebSocketGraphQlTester.java @@ -17,9 +17,13 @@ package org.springframework.graphql.test.tester; import java.net.URI; +import java.util.List; +import java.util.function.Consumer; import reactor.core.publisher.Mono; +import org.springframework.graphql.client.GraphQlClientInterceptor; +import org.springframework.graphql.client.GraphQlTransport; import org.springframework.graphql.client.WebSocketGraphQlClient; import org.springframework.web.reactive.socket.client.WebSocketClient; @@ -81,6 +85,22 @@ public interface WebSocketGraphQlTester extends WebGraphQlTester { */ interface Builder> extends WebGraphQlTester.Builder { + /** + * Configure interceptors to be invoked before delegating to the + * {@link GraphQlTransport} to perform the request. + * @param interceptors the interceptors to add + * @return this builder + */ + B interceptor(GraphQlClientInterceptor... interceptors); + + /** + * Customize the list of interceptors. The provided list is "live", so + * the consumer can inspect and insert interceptors accordingly. + * @param interceptorsConsumer consumer to customize the interceptors with + * @return this builder + */ + B interceptors(Consumer> interceptorsConsumer); + /** * Build the {@code WebSocketGraphQlTester}. */ diff --git a/spring-graphql-test/src/test/java/org/springframework/graphql/test/tester/WebSocketGraphQlTesterTests.java b/spring-graphql-test/src/test/java/org/springframework/graphql/test/tester/WebSocketGraphQlTesterTests.java new file mode 100644 index 00000000..09cab5e0 --- /dev/null +++ b/spring-graphql-test/src/test/java/org/springframework/graphql/test/tester/WebSocketGraphQlTesterTests.java @@ -0,0 +1,76 @@ +/* + * Copyright 2020-2024 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. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.graphql.test.tester; + +import java.net.URI; +import java.time.Duration; +import java.util.concurrent.atomic.AtomicBoolean; + +import org.junit.jupiter.api.Test; +import reactor.core.publisher.Mono; + +import org.springframework.graphql.client.ClientGraphQlRequest; +import org.springframework.graphql.client.ClientGraphQlResponse; +import org.springframework.graphql.client.GraphQlClientInterceptor; +import org.springframework.graphql.client.TestWebSocketClient; +import org.springframework.graphql.client.WebSocketGraphQlClient; +import org.springframework.graphql.execution.MockExecutionGraphQlService; +import org.springframework.graphql.server.WebGraphQlHandler; +import org.springframework.graphql.server.webflux.GraphQlWebSocketHandler; +import org.springframework.http.codec.ClientCodecConfigurer; +import org.springframework.web.reactive.socket.WebSocketHandler; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * Tests for {@link WebSocketGraphQlTester}. + */ +class WebSocketGraphQlTesterTests { + + + @Test + void shouldConfigureInterceptors() { + TestInterceptor testInterceptor = new TestInterceptor(); + TestWebSocketClient webSocketClient = createWebSocketClient(); + WebSocketGraphQlClient client = WebSocketGraphQlClient.builder(URI.create(""), webSocketClient) + .interceptor(testInterceptor) + .build(); + + client.document("{ Query }").execute().block(Duration.ofMillis(500)); + assertThat(testInterceptor.executed).as("Interceptor is not executed").isTrue(); + } + + private TestWebSocketClient createWebSocketClient() { + MockExecutionGraphQlService graphQlService = new MockExecutionGraphQlService(); + graphQlService.setDefaultResponse("{}"); + WebGraphQlHandler graphQlHandler = WebGraphQlHandler.builder(graphQlService).build(); + ClientCodecConfigurer configurer = ClientCodecConfigurer.create(); + WebSocketHandler handler = new GraphQlWebSocketHandler(graphQlHandler, configurer, Duration.ofSeconds(5)); + return new TestWebSocketClient(handler); + } + + class TestInterceptor implements GraphQlClientInterceptor { + + AtomicBoolean executed = new AtomicBoolean(); + + @Override + public Mono intercept(ClientGraphQlRequest request, Chain chain) { + return chain.next(request).doOnNext((response) -> executed.set(true)); + } + } + +}