Refactoring in Client and Tester builder implementations

The default transport-specific client and tester extensions contained
their builder implementations, but it makes more sense the other way
around since the extensions are mainly about the builders they provide.
This commit is contained in:
rstoyanchev
2022-03-29 14:47:35 +01:00
parent f9b84cb8d0
commit b3f13b978a
30 changed files with 1228 additions and 1209 deletions

View File

@@ -0,0 +1,89 @@
/*
* 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.
* 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.util.function.Consumer;
import org.springframework.graphql.ExecutionGraphQlService;
import org.springframework.util.Assert;
/**
* Default {@link ExecutionGraphQlServiceTester.Builder} implementation that
* wraps an {@code ExecutionGraphQlService}.
*
* @author Rossen Stoyanchev
* @since 1.0.0
*/
final class DefaultExecutionGraphQlServiceTesterBuilder
extends AbstractGraphQlTesterBuilder<DefaultExecutionGraphQlServiceTesterBuilder>
implements ExecutionGraphQlServiceTester.Builder<DefaultExecutionGraphQlServiceTesterBuilder> {
private final ExecutionGraphQlService service;
DefaultExecutionGraphQlServiceTesterBuilder(ExecutionGraphQlService service) {
Assert.notNull(service, "GraphQlService is required");
this.service = service;
}
DefaultExecutionGraphQlServiceTesterBuilder(GraphQlServiceGraphQlTransport transport) {
this.service = transport.getGraphQlService();
}
@Override
public ExecutionGraphQlServiceTester build() {
GraphQlServiceGraphQlTransport transport = new GraphQlServiceGraphQlTransport(this.service);
GraphQlTester tester = super.buildGraphQlTester(transport);
return new DefaultExecutionGraphQlServiceTester(tester, transport, getBuilderInitializer());
}
/**
* Default {@link ExecutionGraphQlServiceTester} implementation.
*/
private static class DefaultExecutionGraphQlServiceTester
extends AbstractDelegatingGraphQlTester implements ExecutionGraphQlServiceTester {
private final GraphQlServiceGraphQlTransport transport;
private final Consumer<AbstractGraphQlTesterBuilder<?>> builderInitializer;
private DefaultExecutionGraphQlServiceTester(GraphQlTester tester, GraphQlServiceGraphQlTransport transport,
Consumer<AbstractGraphQlTesterBuilder<?>> builderInitializer) {
super(tester);
Assert.notNull(transport, "GraphQlServiceTransport is required");
Assert.notNull(builderInitializer, "`builderInitializer` is required");
this.transport = transport;
this.builderInitializer = builderInitializer;
}
@Override
public DefaultExecutionGraphQlServiceTesterBuilder mutate() {
DefaultExecutionGraphQlServiceTesterBuilder builder = new DefaultExecutionGraphQlServiceTesterBuilder(this.transport);
this.builderInitializer.accept(builder);
return builder;
}
}
}

View File

@@ -1,87 +0,0 @@
/*
* 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.
* 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.util.function.Consumer;
import org.springframework.graphql.ExecutionGraphQlService;
import org.springframework.util.Assert;
/**
* Default {@link GraphQlServiceTester} that uses a {@link ExecutionGraphQlService} for
* request execution.
*
* @author Rossen Stoyanchev
* @since 1.0.0
*/
final class DefaultGraphQlServiceTester extends AbstractDelegatingGraphQlTester implements GraphQlServiceTester {
private final GraphQlServiceGraphQlTransport transport;
private final Consumer<AbstractGraphQlTesterBuilder<?>> builderInitializer;
private DefaultGraphQlServiceTester(GraphQlTester tester, GraphQlServiceGraphQlTransport transport,
Consumer<AbstractGraphQlTesterBuilder<?>> builderInitializer) {
super(tester);
Assert.notNull(transport, "GraphQlServiceTransport is required");
Assert.notNull(builderInitializer, "`builderInitializer` is required");
this.transport = transport;
this.builderInitializer = builderInitializer;
}
@Override
public Builder<?> mutate() {
Builder<?> builder = new Builder<>(this.transport);
this.builderInitializer.accept(builder);
return builder;
}
/**
* Default {@link GraphQlServiceTester.Builder} implementation.
*/
static class Builder<B extends Builder<B>> extends AbstractGraphQlTesterBuilder<B>
implements GraphQlServiceTester.Builder<B> {
private final ExecutionGraphQlService service;
Builder(ExecutionGraphQlService service) {
Assert.notNull(service, "GraphQlService is required");
this.service = service;
}
Builder(GraphQlServiceGraphQlTransport transport) {
this.service = transport.getGraphQlService();
}
@Override
public GraphQlServiceTester build() {
GraphQlServiceGraphQlTransport transport = new GraphQlServiceGraphQlTransport(this.service);
GraphQlTester tester = super.buildGraphQlTester(transport);
return new DefaultGraphQlServiceTester(tester, transport, getBuilderInitializer());
}
}
}

View File

@@ -1,128 +0,0 @@
/*
* 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.
* 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.util.function.Consumer;
import org.springframework.http.HttpHeaders;
import org.springframework.http.codec.CodecConfigurer;
import org.springframework.test.web.reactive.server.WebTestClient;
import org.springframework.web.util.DefaultUriBuilderFactory;
import org.springframework.web.util.UriBuilderFactory;
import org.springframework.web.util.UriComponentsBuilder;
/**
* Default {@link HttpGraphQlTester} that builds and uses a {@link WebTestClient}
* for request execution.
*
* @author Rossen Stoyanchev
* @since 1.0.0
*/
final class DefaultHttpGraphQlTester extends AbstractDelegatingGraphQlTester implements HttpGraphQlTester {
private final WebTestClient webTestClient;
private final Consumer<AbstractGraphQlTesterBuilder<?>> builderInitializer;
private DefaultHttpGraphQlTester(GraphQlTester graphQlTester, WebTestClient webTestClient,
Consumer<AbstractGraphQlTesterBuilder<?>> builderInitializer) {
super(graphQlTester);
this.webTestClient = webTestClient;
this.builderInitializer = builderInitializer;
}
@Override
public Builder mutate() {
Builder builder = new Builder(this.webTestClient.mutate());
this.builderInitializer.accept(builder);
return builder;
}
/**
* Default {@link HttpGraphQlTester.Builder} implementation.
*/
static final class Builder extends AbstractGraphQlTesterBuilder<Builder>
implements HttpGraphQlTester.Builder<Builder> {
private final WebTestClient.Builder webTestClientBuilder;
Builder(WebTestClient.Builder clientBuilder) {
this.webTestClientBuilder = clientBuilder;
}
@Override
public Builder url(String url) {
this.webTestClientBuilder.baseUrl(url);
return this;
}
@Override
public Builder url(URI url) {
UriBuilderFactory factory = new DefaultUriBuilderFactory(UriComponentsBuilder.fromUri(url));
this.webTestClientBuilder.uriBuilderFactory(factory);
return this;
}
@Override
public Builder header(String name, String... values) {
this.webTestClientBuilder.defaultHeader(name, values);
return this;
}
@Override
public Builder headers(Consumer<HttpHeaders> headersConsumer) {
this.webTestClientBuilder.defaultHeaders(headersConsumer);
return this;
}
@Override
public Builder codecConfigurer(Consumer<CodecConfigurer> codecConsumer) {
this.webTestClientBuilder.codecs(codecConsumer::accept);
return this;
}
@Override
public Builder webTestClient(Consumer<WebTestClient.Builder> configurer) {
configurer.accept(this.webTestClientBuilder);
return this;
}
@Override
public HttpGraphQlTester build() {
registerJsonPathMappingProvider();
WebTestClient client = this.webTestClientBuilder.build();
GraphQlTester tester = super.buildGraphQlTester(new WebTestClientTransport(client));
return new DefaultHttpGraphQlTester(tester, client, getBuilderInitializer());
}
private void registerJsonPathMappingProvider() {
this.webTestClientBuilder.codecs(codecConfigurer ->
configureJsonPathConfig(config -> {
EncoderDecoderMappingProvider provider = new EncoderDecoderMappingProvider(codecConfigurer);
return config.mappingProvider(provider);
}));
}
}
}

View File

@@ -0,0 +1,131 @@
/*
* 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.
* 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.util.function.Consumer;
import org.springframework.http.HttpHeaders;
import org.springframework.http.codec.CodecConfigurer;
import org.springframework.test.web.reactive.server.WebTestClient;
import org.springframework.web.util.DefaultUriBuilderFactory;
import org.springframework.web.util.UriBuilderFactory;
import org.springframework.web.util.UriComponentsBuilder;
/**
* Default {@link HttpGraphQlTester.Builder} implementation, simply wraps a
* {@link WebTestClient.Builder}.
*
* @author Rossen Stoyanchev
* @since 1.0.0
*/
final class DefaultHttpGraphQlTesterBuilder
extends AbstractGraphQlTesterBuilder<DefaultHttpGraphQlTesterBuilder>
implements HttpGraphQlTester.Builder<DefaultHttpGraphQlTesterBuilder> {
private final WebTestClient.Builder webTestClientBuilder;
DefaultHttpGraphQlTesterBuilder(WebTestClient.Builder clientBuilder) {
this.webTestClientBuilder = clientBuilder;
}
@Override
public DefaultHttpGraphQlTesterBuilder url(String url) {
this.webTestClientBuilder.baseUrl(url);
return this;
}
@Override
public DefaultHttpGraphQlTesterBuilder url(URI url) {
UriBuilderFactory factory = new DefaultUriBuilderFactory(UriComponentsBuilder.fromUri(url));
this.webTestClientBuilder.uriBuilderFactory(factory);
return this;
}
@Override
public DefaultHttpGraphQlTesterBuilder header(String name, String... values) {
this.webTestClientBuilder.defaultHeader(name, values);
return this;
}
@Override
public DefaultHttpGraphQlTesterBuilder headers(Consumer<HttpHeaders> headersConsumer) {
this.webTestClientBuilder.defaultHeaders(headersConsumer);
return this;
}
@Override
public DefaultHttpGraphQlTesterBuilder codecConfigurer(Consumer<CodecConfigurer> codecConsumer) {
this.webTestClientBuilder.codecs(codecConsumer::accept);
return this;
}
@Override
public DefaultHttpGraphQlTesterBuilder webTestClient(Consumer<WebTestClient.Builder> configurer) {
configurer.accept(this.webTestClientBuilder);
return this;
}
@Override
public HttpGraphQlTester build() {
registerJsonPathMappingProvider();
WebTestClient client = this.webTestClientBuilder.build();
GraphQlTester tester = super.buildGraphQlTester(new WebTestClientTransport(client));
return new DefaultHttpGraphQlTester(tester, client, getBuilderInitializer());
}
private void registerJsonPathMappingProvider() {
this.webTestClientBuilder.codecs(codecConfigurer ->
configureJsonPathConfig(config -> {
EncoderDecoderMappingProvider provider = new EncoderDecoderMappingProvider(codecConfigurer);
return config.mappingProvider(provider);
}));
}
/**
* Default {@link HttpGraphQlTester} that builds and uses a {@link WebTestClient}
* for request execution.
*/
private static class DefaultHttpGraphQlTester extends AbstractDelegatingGraphQlTester implements HttpGraphQlTester {
private final WebTestClient webTestClient;
private final Consumer<AbstractGraphQlTesterBuilder<?>> builderInitializer;
private DefaultHttpGraphQlTester(GraphQlTester graphQlTester, WebTestClient webTestClient,
Consumer<AbstractGraphQlTesterBuilder<?>> builderInitializer) {
super(graphQlTester);
this.webTestClient = webTestClient;
this.builderInitializer = builderInitializer;
}
@Override
public DefaultHttpGraphQlTesterBuilder mutate() {
DefaultHttpGraphQlTesterBuilder builder = new DefaultHttpGraphQlTesterBuilder(this.webTestClient.mutate());
this.builderInitializer.accept(builder);
return builder;
}
}
}

View File

@@ -1,150 +0,0 @@
/*
* 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.
* 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.util.List;
import java.util.function.Consumer;
import io.rsocket.transport.ClientTransport;
import org.springframework.core.codec.Decoder;
import org.springframework.core.codec.Encoder;
import org.springframework.graphql.client.RSocketGraphQlClient;
import org.springframework.messaging.rsocket.RSocketRequester;
import org.springframework.messaging.rsocket.RSocketStrategies;
import org.springframework.util.MimeType;
/**
* Default {@link RSocketGraphQlTester} that builds and uses an
* {@link RSocketGraphQlClient} for request execution.
*
* @author Rossen Stoyanchev
* @since 1.0.0
*/
public class DefaultRSocketGraphQlTester extends AbstractDelegatingGraphQlTester implements RSocketGraphQlTester {
private final RSocketGraphQlClient rsocketGraphQlClient;
private final Consumer<AbstractGraphQlTesterBuilder<?>> builderInitializer;
DefaultRSocketGraphQlTester(
GraphQlTester delegate, RSocketGraphQlClient rsocketGraphQlClient,
Consumer<AbstractGraphQlTesterBuilder<?>> builderInitializer) {
super(delegate);
this.rsocketGraphQlClient = rsocketGraphQlClient;
this.builderInitializer = builderInitializer;
}
@Override
public RSocketGraphQlTester.Builder<?> mutate() {
Builder builder = new Builder(this.rsocketGraphQlClient);
this.builderInitializer.accept(builder);
return builder;
}
/**
* Default implementation of {@link GraphQlTester.Builder}.
*/
static final class Builder extends AbstractGraphQlTesterBuilder<Builder> implements RSocketGraphQlTester.Builder<Builder> {
private final RSocketGraphQlClient.Builder<?> rsocketGraphQlClientBuilder;
/**
* Constructor to start via {@link RSocketGraphQlTester#builder()}.
*/
Builder() {
this.rsocketGraphQlClientBuilder = RSocketGraphQlClient.builder();
}
/**
* Constructor to start via {@link RSocketGraphQlTester#builder(RSocketRequester.Builder)}.
*/
Builder(RSocketRequester.Builder requesterBuilder) {
this.rsocketGraphQlClientBuilder = RSocketGraphQlClient.builder(requesterBuilder);
}
/**
* Constructor to mutate.
* @param rsocketGraphQlClient the underlying client with the current state
*/
public Builder(RSocketGraphQlClient rsocketGraphQlClient) {
this.rsocketGraphQlClientBuilder = rsocketGraphQlClient.mutate();
}
@Override
public Builder tcp(String host, int port) {
this.rsocketGraphQlClientBuilder.tcp(host, port);
return this;
}
@Override
public Builder webSocket(URI uri) {
this.rsocketGraphQlClientBuilder.webSocket(uri);
return this;
}
@Override
public Builder clientTransport(ClientTransport clientTransport) {
this.rsocketGraphQlClientBuilder.clientTransport(clientTransport);
return this;
}
@Override
public Builder dataMimeType(MimeType dataMimeType) {
this.rsocketGraphQlClientBuilder.dataMimeType(dataMimeType);
return this;
}
@Override
public Builder route(String route) {
this.rsocketGraphQlClientBuilder.route(route);
return this;
}
@Override
public Builder rsocketRequester(Consumer<RSocketRequester.Builder> requesterConsumer) {
this.rsocketGraphQlClientBuilder.rsocketRequester(requesterConsumer);
return this;
}
@Override
public RSocketGraphQlTester build() {
registerJsonPathMappingProvider();
RSocketGraphQlClient rsocketGraphQlClient = this.rsocketGraphQlClientBuilder.build();
GraphQlTester graphQlTester = super.buildGraphQlTester(asTransport(rsocketGraphQlClient));
return new DefaultRSocketGraphQlTester(graphQlTester, rsocketGraphQlClient, getBuilderInitializer());
}
private void registerJsonPathMappingProvider() {
this.rsocketGraphQlClientBuilder.rsocketRequester(builder ->
builder.rsocketStrategies(strategiesBuilder ->
configureJsonPathConfig(config -> {
RSocketStrategies strategies = strategiesBuilder.build();
List<Encoder<?>> encoders = strategies.encoders();
List<Decoder<?>> decoders = strategies.decoders();
return config.mappingProvider(new EncoderDecoderMappingProvider(encoders, decoders));
})));
}
}
}

View File

@@ -0,0 +1,153 @@
/*
* 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.
* 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.util.List;
import java.util.function.Consumer;
import io.rsocket.transport.ClientTransport;
import org.springframework.core.codec.Decoder;
import org.springframework.core.codec.Encoder;
import org.springframework.graphql.client.RSocketGraphQlClient;
import org.springframework.messaging.rsocket.RSocketRequester;
import org.springframework.messaging.rsocket.RSocketStrategies;
import org.springframework.util.MimeType;
/**
* Default implementation of {@link RSocketGraphQlTester.Builder} that wraps
* an {@link RSocketGraphQlClient.Builder}.
*
* @author Rossen Stoyanchev
* @since 1.0.0
*/
public class DefaultRSocketGraphQlTesterBuilder
extends AbstractGraphQlTesterBuilder<DefaultRSocketGraphQlTesterBuilder>
implements RSocketGraphQlTester.Builder<DefaultRSocketGraphQlTesterBuilder> {
private final RSocketGraphQlClient.Builder<?> rsocketGraphQlClientBuilder;
/**
* Constructor to start via {@link RSocketGraphQlTester#builder()}.
*/
DefaultRSocketGraphQlTesterBuilder() {
this.rsocketGraphQlClientBuilder = RSocketGraphQlClient.builder();
}
/**
* Constructor to start via {@link RSocketGraphQlTester#builder(RSocketRequester.Builder)}.
*/
DefaultRSocketGraphQlTesterBuilder(RSocketRequester.Builder requesterBuilder) {
this.rsocketGraphQlClientBuilder = RSocketGraphQlClient.builder(requesterBuilder);
}
/**
* Constructor to mutate.
* @param rsocketGraphQlClient the underlying client with the current state
*/
public DefaultRSocketGraphQlTesterBuilder(RSocketGraphQlClient rsocketGraphQlClient) {
this.rsocketGraphQlClientBuilder = rsocketGraphQlClient.mutate();
}
@Override
public DefaultRSocketGraphQlTesterBuilder tcp(String host, int port) {
this.rsocketGraphQlClientBuilder.tcp(host, port);
return this;
}
@Override
public DefaultRSocketGraphQlTesterBuilder webSocket(URI uri) {
this.rsocketGraphQlClientBuilder.webSocket(uri);
return this;
}
@Override
public DefaultRSocketGraphQlTesterBuilder clientTransport(ClientTransport clientTransport) {
this.rsocketGraphQlClientBuilder.clientTransport(clientTransport);
return this;
}
@Override
public DefaultRSocketGraphQlTesterBuilder dataMimeType(MimeType dataMimeType) {
this.rsocketGraphQlClientBuilder.dataMimeType(dataMimeType);
return this;
}
@Override
public DefaultRSocketGraphQlTesterBuilder route(String route) {
this.rsocketGraphQlClientBuilder.route(route);
return this;
}
@Override
public DefaultRSocketGraphQlTesterBuilder rsocketRequester(Consumer<RSocketRequester.Builder> requesterConsumer) {
this.rsocketGraphQlClientBuilder.rsocketRequester(requesterConsumer);
return this;
}
@Override
public RSocketGraphQlTester build() {
registerJsonPathMappingProvider();
RSocketGraphQlClient rsocketGraphQlClient = this.rsocketGraphQlClientBuilder.build();
GraphQlTester graphQlTester = super.buildGraphQlTester(asTransport(rsocketGraphQlClient));
return new DefaultRSocketGraphQlTester(graphQlTester, rsocketGraphQlClient, getBuilderInitializer());
}
private void registerJsonPathMappingProvider() {
this.rsocketGraphQlClientBuilder.rsocketRequester(builder ->
builder.rsocketStrategies(strategiesBuilder ->
configureJsonPathConfig(config -> {
RSocketStrategies strategies = strategiesBuilder.build();
List<Encoder<?>> encoders = strategies.encoders();
List<Decoder<?>> decoders = strategies.decoders();
return config.mappingProvider(new EncoderDecoderMappingProvider(encoders, decoders));
})));
}
/**
* Default {@link RSocketGraphQlTester} implementation.
*/
private static class DefaultRSocketGraphQlTester extends AbstractDelegatingGraphQlTester implements RSocketGraphQlTester {
private final RSocketGraphQlClient rsocketGraphQlClient;
private final Consumer<AbstractGraphQlTesterBuilder<?>> builderInitializer;
DefaultRSocketGraphQlTester(
GraphQlTester delegate, RSocketGraphQlClient rsocketGraphQlClient,
Consumer<AbstractGraphQlTesterBuilder<?>> builderInitializer) {
super(delegate);
this.rsocketGraphQlClient = rsocketGraphQlClient;
this.builderInitializer = builderInitializer;
}
@Override
public RSocketGraphQlTester.Builder<?> mutate() {
DefaultRSocketGraphQlTesterBuilder builder = new DefaultRSocketGraphQlTesterBuilder(this.rsocketGraphQlClient);
this.builderInitializer.accept(builder);
return builder;
}
}
}

View File

@@ -0,0 +1,79 @@
/*
* 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.
* 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.util.function.Consumer;
import org.springframework.graphql.client.GraphQlTransport;
import org.springframework.util.Assert;
/**
* Default {@link GraphQlTester.Builder} with a given, externally prepared transport.
*
* @author Rossen Stoyanchev
* @since 1.0.0
*/
final class DefaultTransportGraphQlTesterBuilder
extends AbstractGraphQlTesterBuilder<DefaultTransportGraphQlTesterBuilder> {
private final GraphQlTransport transport;
DefaultTransportGraphQlTesterBuilder(GraphQlTransport transport) {
this.transport = transport;
}
@Override
public GraphQlTester build() {
GraphQlTester tester = super.buildGraphQlTester(this.transport);
return new DefaultTransportGraphQlTester(tester, this.transport, getBuilderInitializer());
}
/**
* {@link GraphQlTester} with a given transport.
*/
private static class DefaultTransportGraphQlTester extends AbstractDelegatingGraphQlTester {
private final GraphQlTransport transport;
private final Consumer<AbstractGraphQlTesterBuilder<?>> builderInitializer;
private DefaultTransportGraphQlTester(
GraphQlTester delegate, GraphQlTransport transport,
Consumer<AbstractGraphQlTesterBuilder<?>> builderInitializer) {
super(delegate);
Assert.notNull(transport, "GraphQlTransport is required");
Assert.notNull(builderInitializer, "'builderInitializer' is required");
this.transport = transport;
this.builderInitializer = builderInitializer;
}
@Override
public DefaultTransportGraphQlTesterBuilder mutate() {
DefaultTransportGraphQlTesterBuilder builder = new DefaultTransportGraphQlTesterBuilder(this.transport);
this.builderInitializer.accept(builder);
return builder;
}
}
}

View File

@@ -28,114 +28,111 @@ import org.springframework.http.codec.CodecConfigurer;
import org.springframework.util.Assert;
import org.springframework.web.util.DefaultUriBuilderFactory;
/**
* Default {@link WebGraphQlTester} that uses {@link WebGraphQlHandler} for
* request execution.
* Default implementation for {@link WebGraphQlTester} that initializes a
* {@link WebGraphQlHandler} for request execution.
*
* @author Rossen Stoyanchev
* @since 1.0.0
*/
final class DefaultWebGraphQlTester extends AbstractDelegatingGraphQlTester implements WebGraphQlTester {
final class DefaultWebGraphQlTesterBuilder
extends AbstractGraphQlTesterBuilder<DefaultWebGraphQlTesterBuilder>
implements WebGraphQlTester.Builder<DefaultWebGraphQlTesterBuilder> {
private final WebGraphQlHandlerGraphQlTransport transport;
private URI url = URI.create("");
private final Consumer<AbstractGraphQlTesterBuilder<?>> builderInitializer;
private final HttpHeaders headers = new HttpHeaders();
private final WebGraphQlHandler handler;
private CodecConfigurer codecConfigurer = ClientCodecConfigurer.create();
private DefaultWebGraphQlTester(GraphQlTester tester, WebGraphQlHandlerGraphQlTransport transport,
Consumer<AbstractGraphQlTesterBuilder<?>> builderInitializer) {
DefaultWebGraphQlTesterBuilder(WebGraphQlHandler handler) {
Assert.notNull(handler, "WebGraphQlHandler is required");
this.handler = handler;
}
super(tester);
this.transport = transport;
this.builderInitializer = builderInitializer;
DefaultWebGraphQlTesterBuilder(WebGraphQlHandlerGraphQlTransport transport) {
this.url = transport.getUrl();
this.headers.putAll(transport.getHeaders());
this.handler = transport.getGraphQlHandler();
this.codecConfigurer = transport.getCodecConfigurer();
}
@Override
public Builder<?> mutate() {
Builder<?> builder = new Builder<>(this.transport);
this.builderInitializer.accept(builder);
return builder;
public DefaultWebGraphQlTesterBuilder url(String url) {
return url(new DefaultUriBuilderFactory().uriString(url).build());
}
@Override
public DefaultWebGraphQlTesterBuilder url(URI url) {
this.url = url;
return this;
}
@Override
public DefaultWebGraphQlTesterBuilder header(String name, String... values) {
this.headers.put(name, Arrays.asList(values));
return this;
}
@Override
public DefaultWebGraphQlTesterBuilder headers(Consumer<HttpHeaders> headersConsumer) {
headersConsumer.accept(this.headers);
return this;
}
@Override
public DefaultWebGraphQlTesterBuilder codecConfigurer(Consumer<CodecConfigurer> codecConfigurerConsumer) {
codecConfigurerConsumer.accept(this.codecConfigurer);
return this;
}
@Override
public WebGraphQlTester build() {
registerJsonPathMappingProvider();
WebGraphQlHandlerGraphQlTransport transport =
new WebGraphQlHandlerGraphQlTransport(this.url, this.headers, this.handler, this.codecConfigurer);
GraphQlTester tester = super.buildGraphQlTester(transport);
return new DefaultWebGraphQlTester(tester, transport, getBuilderInitializer());
}
private void registerJsonPathMappingProvider() {
configureJsonPathConfig(jsonPathConfig -> {
EncoderDecoderMappingProvider provider = new EncoderDecoderMappingProvider(this.codecConfigurer);
return jsonPathConfig.mappingProvider(provider);
});
}
/**
* Base builder implementation for all Web transport extensions.
* Default {@link WebGraphQlTester} implementation.
*/
static class Builder<B extends Builder<B>> extends AbstractGraphQlTesterBuilder<B>
implements WebGraphQlTester.Builder<B> {
private static class DefaultWebGraphQlTester extends AbstractDelegatingGraphQlTester implements WebGraphQlTester {
private URI url = URI.create("");
private final WebGraphQlHandlerGraphQlTransport transport;
private final HttpHeaders headers = new HttpHeaders();
private final Consumer<AbstractGraphQlTesterBuilder<?>> builderInitializer;
private final WebGraphQlHandler handler;
private DefaultWebGraphQlTester(GraphQlTester tester, WebGraphQlHandlerGraphQlTransport transport,
Consumer<AbstractGraphQlTesterBuilder<?>> builderInitializer) {
private CodecConfigurer codecConfigurer = ClientCodecConfigurer.create();
Builder(WebGraphQlHandler handler) {
Assert.notNull(handler, "WebGraphQlHandler is required");
this.handler = handler;
}
Builder(WebGraphQlHandlerGraphQlTransport transport) {
this.url = transport.getUrl();
this.headers.putAll(transport.getHeaders());
this.handler = transport.getGraphQlHandler();
this.codecConfigurer = transport.getCodecConfigurer();
super(tester);
this.transport = transport;
this.builderInitializer = builderInitializer;
}
@Override
public B url(String url) {
return url(new DefaultUriBuilderFactory().uriString(url).build());
}
@Override
public B url(URI url) {
this.url = url;
return self();
}
@Override
public B header(String name, String... values) {
this.headers.put(name, Arrays.asList(values));
return self();
}
@Override
public B headers(Consumer<HttpHeaders> headersConsumer) {
headersConsumer.accept(this.headers);
return self();
}
@Override
public B codecConfigurer(Consumer<CodecConfigurer> codecConfigurerConsumer) {
codecConfigurerConsumer.accept(this.codecConfigurer);
return self();
}
@SuppressWarnings("unchecked")
protected <T extends B> T self() {
return (T) this;
}
@Override
public WebGraphQlTester build() {
registerJsonPathMappingProvider();
WebGraphQlHandlerGraphQlTransport transport =
new WebGraphQlHandlerGraphQlTransport(this.url, this.headers, this.handler, this.codecConfigurer);
GraphQlTester tester = super.buildGraphQlTester(transport);
return new DefaultWebGraphQlTester(tester, transport, getBuilderInitializer());
}
private void registerJsonPathMappingProvider() {
configureJsonPathConfig(jsonPathConfig -> {
EncoderDecoderMappingProvider provider = new EncoderDecoderMappingProvider(this.codecConfigurer);
return jsonPathConfig.mappingProvider(provider);
});
public DefaultWebGraphQlTesterBuilder mutate() {
DefaultWebGraphQlTesterBuilder builder = new DefaultWebGraphQlTesterBuilder(this.transport);
this.builderInitializer.accept(builder);
return builder;
}
}

View File

@@ -28,127 +28,130 @@ import org.springframework.http.codec.CodecConfigurer;
import org.springframework.util.Assert;
import org.springframework.web.reactive.socket.client.WebSocketClient;
/**
* Default {@link WebSocketGraphQlTester} that builds and uses a
* {@link WebSocketGraphQlClient} for request execution.
* Default {@link WebSocketGraphQlTester.Builder} implementation, wraps a
* {@link WebSocketGraphQlClient.Builder}.
*
* @author Rossen Stoyanchev
* @since 1.0.0
*/
final class DefaultWebSocketGraphQlTester extends AbstractDelegatingGraphQlTester implements WebSocketGraphQlTester {
final class DefaultWebSocketGraphQlTesterBuilder
extends AbstractGraphQlTesterBuilder<DefaultWebSocketGraphQlTesterBuilder>
implements WebSocketGraphQlTester.Builder<DefaultWebSocketGraphQlTesterBuilder> {
private final WebSocketGraphQlClient webSocketGraphQlClient;
private final Consumer<AbstractGraphQlTesterBuilder<?>> builderInitializer;
private final WebSocketGraphQlClient.Builder<?> graphQlClientBuilder;
private DefaultWebSocketGraphQlTester(
GraphQlTester graphQlTester, WebSocketGraphQlClient webSocketGraphQlClient,
Consumer<AbstractGraphQlTesterBuilder<?>> builderInitializer) {
/**
* Constructor to start via {@link WebSocketGraphQlTester#builder(String, WebSocketClient)}.
*/
DefaultWebSocketGraphQlTesterBuilder(String url, WebSocketClient webSocketClient) {
Assert.notNull(webSocketClient, "WebSocketClient is required");
this.graphQlClientBuilder = WebSocketGraphQlClient.builder(url, webSocketClient);
}
super(graphQlTester);
this.webSocketGraphQlClient = webSocketGraphQlClient;
this.builderInitializer = builderInitializer;
/**
* Constructor to start via {@link WebSocketGraphQlTester#builder(URI, WebSocketClient)}.
*/
DefaultWebSocketGraphQlTesterBuilder(URI url, WebSocketClient webSocketClient) {
Assert.notNull(webSocketClient, "WebSocketClient is required");
this.graphQlClientBuilder = WebSocketGraphQlClient.builder(url, webSocketClient);
}
/**
* Constructor to mutate.
* @param client the underlying client with the current state
*/
DefaultWebSocketGraphQlTesterBuilder(WebSocketGraphQlClient client) {
Assert.notNull(client, "WebSocketGraphQlClient is required");
this.graphQlClientBuilder = client.mutate();
}
@Override
public Mono<Void> start() {
return this.webSocketGraphQlClient.start();
public DefaultWebSocketGraphQlTesterBuilder url(String url) {
this.graphQlClientBuilder.url(url);
return this;
}
@Override
public Mono<Void> stop() {
return this.webSocketGraphQlClient.stop();
public DefaultWebSocketGraphQlTesterBuilder url(URI url) {
this.graphQlClientBuilder.url(url);
return this;
}
@Override
public Builder mutate() {
Builder builder = new Builder(this.webSocketGraphQlClient);
this.builderInitializer.accept(builder);
return builder;
public DefaultWebSocketGraphQlTesterBuilder header(String name, String... values) {
this.graphQlClientBuilder.header(name, values);
return this;
}
@Override
public DefaultWebSocketGraphQlTesterBuilder headers(Consumer<HttpHeaders> headersConsumer) {
this.graphQlClientBuilder.headers(headersConsumer);
return this;
}
@Override
public DefaultWebSocketGraphQlTesterBuilder codecConfigurer(Consumer<CodecConfigurer> codecsConsumer) {
this.graphQlClientBuilder.codecConfigurer(codecsConsumer);
return this;
}
@Override
public WebSocketGraphQlTester build() {
registerJsonPathMappingProvider();
WebSocketGraphQlClient client = this.graphQlClientBuilder.build();
GraphQlTester graphQlTester = super.buildGraphQlTester(asTransport(client));
return new DefaultWebSocketGraphQlTester(graphQlTester, client, getBuilderInitializer());
}
private void registerJsonPathMappingProvider() {
this.graphQlClientBuilder.codecConfigurer(codecConfigurer -> {
configureJsonPathConfig(jsonPathConfig -> {
EncoderDecoderMappingProvider provider = new EncoderDecoderMappingProvider(codecConfigurer);
return jsonPathConfig.mappingProvider(provider);
});
});
}
/**
* Default {@link WebSocketGraphQlTester.Builder} implementation.
* Default {@link WebSocketGraphQlTester} implementation.
*/
static final class Builder extends AbstractGraphQlTesterBuilder<Builder> implements WebSocketGraphQlTester.Builder<Builder> {
private static class DefaultWebSocketGraphQlTester extends AbstractDelegatingGraphQlTester implements WebSocketGraphQlTester {
private final WebSocketGraphQlClient.Builder<?> graphQlClientBuilder;
private final WebSocketGraphQlClient client;
/**
* Constructor to start via {@link WebSocketGraphQlTester#builder(String, WebSocketClient)}.
*/
Builder(String url, WebSocketClient webSocketClient) {
Assert.notNull(webSocketClient, "WebSocketClient is required");
this.graphQlClientBuilder = WebSocketGraphQlClient.builder(url, webSocketClient);
}
private final Consumer<AbstractGraphQlTesterBuilder<?>> builderInitializer;
/**
* Constructor to start via {@link WebSocketGraphQlTester#builder(URI, WebSocketClient)}.
*/
Builder(URI url, WebSocketClient webSocketClient) {
Assert.notNull(webSocketClient, "WebSocketClient is required");
this.graphQlClientBuilder = WebSocketGraphQlClient.builder(url, webSocketClient);
}
private DefaultWebSocketGraphQlTester(
GraphQlTester graphQlTester, WebSocketGraphQlClient client,
Consumer<AbstractGraphQlTesterBuilder<?>> builderInitializer) {
/**
* Constructor to mutate.
* @param client the underlying client with the current state
*/
Builder(WebSocketGraphQlClient client) {
Assert.notNull(client, "WebSocketGraphQlClient is required");
this.graphQlClientBuilder = client.mutate();
}
@Override
public Builder url(String url) {
this.graphQlClientBuilder.url(url);
return this;
super(graphQlTester);
this.client = client;
this.builderInitializer = builderInitializer;
}
@Override
public Builder url(URI url) {
this.graphQlClientBuilder.url(url);
return this;
public Mono<Void> start() {
return this.client.start();
}
@Override
public Builder header(String name, String... values) {
this.graphQlClientBuilder.header(name, values);
return this;
public Mono<Void> stop() {
return this.client.stop();
}
@Override
public Builder headers(Consumer<HttpHeaders> headersConsumer) {
this.graphQlClientBuilder.headers(headersConsumer);
return this;
public DefaultWebSocketGraphQlTesterBuilder mutate() {
DefaultWebSocketGraphQlTesterBuilder builder = new DefaultWebSocketGraphQlTesterBuilder(this.client);
this.builderInitializer.accept(builder);
return builder;
}
@Override
public Builder codecConfigurer(Consumer<CodecConfigurer> codecsConsumer) {
this.graphQlClientBuilder.codecConfigurer(codecsConsumer);
return this;
}
@Override
public WebSocketGraphQlTester build() {
registerJsonPathMappingProvider();
WebSocketGraphQlClient client = this.graphQlClientBuilder.build();
GraphQlTester graphQlTester = super.buildGraphQlTester(asTransport(client));
return new DefaultWebSocketGraphQlTester(graphQlTester, client, getBuilderInitializer());
}
private void registerJsonPathMappingProvider() {
this.graphQlClientBuilder.codecConfigurer(codecConfigurer -> {
configureJsonPathConfig(jsonPathConfig -> {
EncoderDecoderMappingProvider provider = new EncoderDecoderMappingProvider(codecConfigurer);
return jsonPathConfig.mappingProvider(provider);
});
});
}
}
}

View File

@@ -19,13 +19,13 @@ package org.springframework.graphql.test.tester;
import org.springframework.graphql.ExecutionGraphQlService;
/**
* {@link GraphQlTester} that executes requests through a {@link ExecutionGraphQlService}
* Use it for server-side tests, without a client.
* {@link GraphQlTester} that executes requests through an
* {@link ExecutionGraphQlService} on the server side, without a client.
*
* @author Rossen Stoyanchev
* @since 1.0.0
*/
public interface GraphQlServiceTester extends GraphQlTester {
public interface ExecutionGraphQlServiceTester extends GraphQlTester {
@Override
@@ -33,30 +33,30 @@ public interface GraphQlServiceTester extends GraphQlTester {
/**
* Create a {@link GraphQlServiceTester} instance.
* Create a {@link ExecutionGraphQlServiceTester} instance.
*/
static GraphQlServiceTester create(ExecutionGraphQlService service) {
static ExecutionGraphQlServiceTester create(ExecutionGraphQlService service) {
return builder(service).build();
}
/**
* Return a builder for {@link GraphQlServiceTester}.
* Return a builder for {@link ExecutionGraphQlServiceTester}.
*/
static GraphQlServiceTester.Builder<?> builder(ExecutionGraphQlService service) {
return new DefaultGraphQlServiceTester.Builder<>(service);
static ExecutionGraphQlServiceTester.Builder<?> builder(ExecutionGraphQlService service) {
return new DefaultExecutionGraphQlServiceTesterBuilder(service);
}
/**
* Default {@link GraphQlServiceTester.Builder} implementation.
* Default {@link ExecutionGraphQlServiceTester.Builder} implementation.
*/
interface Builder<B extends Builder<B>> extends GraphQlTester.Builder<B> {
/**
* Build a {@link GraphQlServiceTester} instance.
* Build a {@link ExecutionGraphQlServiceTester} instance.
*/
@Override
GraphQlServiceTester build();
ExecutionGraphQlServiceTester build();
}

View File

@@ -1,77 +0,0 @@
/*
* 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.
* 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.util.function.Consumer;
import org.springframework.graphql.client.GraphQlTransport;
import org.springframework.util.Assert;
/**
* {@link GraphQlTester} with a given, externally prepared transport.
*
* @author Rossen Stoyanchev
* @since 1.0.0
*/
final class GenericGraphQlTester extends AbstractDelegatingGraphQlTester {
private final GraphQlTransport transport;
private final Consumer<AbstractGraphQlTesterBuilder<?>> builderInitializer;
private GenericGraphQlTester(
GraphQlTester delegate, GraphQlTransport transport,
Consumer<AbstractGraphQlTesterBuilder<?>> builderInitializer) {
super(delegate);
Assert.notNull(transport, "GraphQlTransport is required");
Assert.notNull(builderInitializer, "'builderInitializer' is required");
this.transport = transport;
this.builderInitializer = builderInitializer;
}
@Override
public Builder mutate() {
Builder builder = new Builder(this.transport);
this.builderInitializer.accept(builder);
return builder;
}
/**
* Default {@link GraphQlTester.Builder} with a given transport.
*/
static final class Builder extends AbstractGraphQlTesterBuilder<Builder> {
private final GraphQlTransport transport;
Builder(GraphQlTransport transport) {
this.transport = transport;
}
@Override
public GraphQlTester build() {
GraphQlTester tester = super.buildGraphQlTester(this.transport);
return new GenericGraphQlTester(tester, this.transport, getBuilderInitializer());
}
}
}

View File

@@ -43,7 +43,7 @@ import org.springframework.lang.Nullable;
*
* <p>To test on the server side, without a client, see the following:
* <ul>
* <li>{@link GraphQlServiceTester}
* <li>{@link ExecutionGraphQlServiceTester}
* <li>{@link WebGraphQlTester}
* </ul>
*
@@ -88,7 +88,7 @@ public interface GraphQlTester {
* @return the builder for further initialization
*/
static GraphQlTester.Builder<?> builder(GraphQlTransport transport) {
return new GenericGraphQlTester.Builder(transport);
return new DefaultTransportGraphQlTesterBuilder(transport);
}

View File

@@ -47,7 +47,7 @@ public interface HttpGraphQlTester extends WebGraphQlTester {
* the underlying {@link WebTestClient} through the given builder.
*/
static HttpGraphQlTester.Builder<?> builder(WebTestClient.Builder webTestClientBuilder) {
return new DefaultHttpGraphQlTester.Builder(webTestClientBuilder);
return new DefaultHttpGraphQlTesterBuilder(webTestClientBuilder);
}

View File

@@ -44,14 +44,14 @@ public interface RSocketGraphQlTester extends GraphQlTester {
* and adding JSON codecs.
*/
static RSocketGraphQlTester.Builder<?> builder() {
return new DefaultRSocketGraphQlTester.Builder();
return new DefaultRSocketGraphQlTesterBuilder();
}
/**
* Start with a given {@link #builder()}.
*/
static RSocketGraphQlTester.Builder<?> builder(RSocketRequester.Builder requesterBuilder) {
return new DefaultRSocketGraphQlTester.Builder(requesterBuilder);
return new DefaultRSocketGraphQlTesterBuilder(requesterBuilder);
}

View File

@@ -25,7 +25,7 @@ import org.springframework.http.codec.CodecConfigurer;
/**
* Server-side tester, without a client, that executes requests through a
* {@link WebGraphQlHandler}. Similar to {@link GraphQlServiceTester} but also
* {@link WebGraphQlHandler}. Similar to {@link ExecutionGraphQlServiceTester} but also
* adding a web processing layer with a {@code WebGraphQlInterceptor}
* chain.
*
@@ -53,7 +53,7 @@ public interface WebGraphQlTester extends GraphQlTester {
* @param graphQlHandler the handler to execute requests
*/
static WebGraphQlTester.Builder<?> builder(WebGraphQlHandler graphQlHandler) {
return new DefaultWebGraphQlTester.Builder<>(graphQlHandler);
return new DefaultWebGraphQlTesterBuilder(graphQlHandler);
}

View File

@@ -62,7 +62,7 @@ public interface WebSocketGraphQlTester extends WebGraphQlTester {
* @param webSocketClient the underlying transport client to use
*/
static WebSocketGraphQlTester.Builder<?> builder(String url, WebSocketClient webSocketClient) {
return new DefaultWebSocketGraphQlTester.Builder(url, webSocketClient);
return new DefaultWebSocketGraphQlTesterBuilder(url, webSocketClient);
}
/**
@@ -71,7 +71,7 @@ public interface WebSocketGraphQlTester extends WebGraphQlTester {
* @param webSocketClient the underlying transport client to use
*/
static WebSocketGraphQlTester.Builder<?> builder(URI url, WebSocketClient webSocketClient) {
return new DefaultWebSocketGraphQlTester.Builder(url, webSocketClient);
return new DefaultWebSocketGraphQlTesterBuilder(url, webSocketClient);
}

View File

@@ -50,7 +50,7 @@ public class GraphQlTesterTestSupport {
private final ExecutionGraphQlService graphQlService = mock(ExecutionGraphQlService.class);
private final GraphQlTester.Builder<?> graphQlTesterBuilder = GraphQlServiceTester.builder(this.graphQlService);
private final GraphQlTester.Builder<?> graphQlTesterBuilder = ExecutionGraphQlServiceTester.builder(this.graphQlService);
private final GraphQlTester graphQlTester = this.graphQlTesterBuilder.build();