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
This commit is contained in:
Brian Clozel
2024-04-19 15:34:07 +02:00
parent fbb08c4c46
commit c9556035ca
3 changed files with 116 additions and 2 deletions

View File

@@ -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<GraphQlClientInterceptor> 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<List<GraphQlClientInterceptor>> 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());
}

View File

@@ -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<B extends Builder<B>> extends WebGraphQlTester.Builder<B> {
/**
* 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<List<GraphQlClientInterceptor>> interceptorsConsumer);
/**
* Build the {@code WebSocketGraphQlTester}.
*/

View File

@@ -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<ClientGraphQlResponse> intercept(ClientGraphQlRequest request, Chain chain) {
return chain.next(request).doOnNext((response) -> executed.set(true));
}
}
}