mirror of
https://github.com/spring-projects/spring-framework
synced 2026-06-08 17:33:33 +00:00
Update RestTestClient builder hierarchy
Add concrete classes with specified generics for each MockMvc setup Ensure Builder methods return the concrete class See gh-34428
This commit is contained in:
+1
-3
@@ -155,7 +155,7 @@ public interface WebTestClient {
|
||||
|
||||
|
||||
/**
|
||||
* Return a builder to mutate properties of this web test client.
|
||||
* Return a builder to mutate properties of this test client.
|
||||
*/
|
||||
Builder mutate();
|
||||
|
||||
@@ -171,8 +171,6 @@ public interface WebTestClient {
|
||||
WebTestClient mutateWith(WebTestClientConfigurer configurer);
|
||||
|
||||
|
||||
// Static factory methods
|
||||
|
||||
/**
|
||||
* Use this server setup to test one {@code @Controller} at a time.
|
||||
* This option loads the default configuration of
|
||||
|
||||
-49
@@ -1,49 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-present 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.test.web.servlet.client;
|
||||
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import org.springframework.test.web.servlet.MockMvcBuilder;
|
||||
|
||||
/**
|
||||
* Default implementation of {@link RestTestClient.MockServerBuilder}.
|
||||
* @author Rob Worsnop
|
||||
* @param <M> the type of the {@link MockMvcBuilder} to use for building the mock server
|
||||
*/
|
||||
class DefaultMockServerBuilder<M extends MockMvcBuilder>
|
||||
extends DefaultRestTestClientBuilder<RestTestClient.MockServerBuilder<M>>
|
||||
implements RestTestClient.MockServerBuilder<M> {
|
||||
|
||||
private final M builder;
|
||||
|
||||
public DefaultMockServerBuilder(M builder) {
|
||||
this.builder = builder;
|
||||
}
|
||||
|
||||
@Override
|
||||
public RestTestClient.MockServerBuilder<M> configureServer(Consumer<M> consumer) {
|
||||
consumer.accept(this.builder);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public RestTestClient build() {
|
||||
this.restClientBuilder.requestFactory(new MockMvcClientHttpRequestFactory(this.builder.build()));
|
||||
return super.build();
|
||||
}
|
||||
}
|
||||
+87
-15
@@ -18,9 +18,20 @@ package org.springframework.test.web.servlet.client;
|
||||
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.client.ClientHttpRequestFactory;
|
||||
import org.springframework.test.web.servlet.MockMvc;
|
||||
import org.springframework.test.web.servlet.MockMvcBuilder;
|
||||
import org.springframework.test.web.servlet.setup.DefaultMockMvcBuilder;
|
||||
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
|
||||
import org.springframework.test.web.servlet.setup.RouterFunctionMockMvcBuilder;
|
||||
import org.springframework.test.web.servlet.setup.StandaloneMockMvcBuilder;
|
||||
import org.springframework.util.MultiValueMap;
|
||||
import org.springframework.web.client.RestClient;
|
||||
import org.springframework.web.context.WebApplicationContext;
|
||||
import org.springframework.web.servlet.function.RouterFunction;
|
||||
import org.springframework.web.util.UriBuilderFactory;
|
||||
|
||||
/**
|
||||
@@ -33,7 +44,7 @@ import org.springframework.web.util.UriBuilderFactory;
|
||||
*/
|
||||
class DefaultRestTestClientBuilder<B extends RestTestClient.Builder<B>> implements RestTestClient.Builder<B> {
|
||||
|
||||
protected final RestClient.Builder restClientBuilder;
|
||||
private final RestClient.Builder restClientBuilder;
|
||||
|
||||
|
||||
DefaultRestTestClientBuilder() {
|
||||
@@ -46,49 +57,110 @@ class DefaultRestTestClientBuilder<B extends RestTestClient.Builder<B>> implemen
|
||||
|
||||
|
||||
@Override
|
||||
public RestTestClient.Builder<B> baseUrl(String baseUrl) {
|
||||
public <T extends B> T baseUrl(String baseUrl) {
|
||||
this.restClientBuilder.baseUrl(baseUrl);
|
||||
return this;
|
||||
return self();
|
||||
}
|
||||
|
||||
@Override
|
||||
public RestTestClient.Builder<B> uriBuilderFactory(UriBuilderFactory uriFactory) {
|
||||
public <T extends B> T uriBuilderFactory(UriBuilderFactory uriFactory) {
|
||||
this.restClientBuilder.uriBuilderFactory(uriFactory);
|
||||
return this;
|
||||
return self();
|
||||
}
|
||||
|
||||
@Override
|
||||
public RestTestClient.Builder<B> defaultHeader(String headerName, String... headerValues) {
|
||||
public <T extends B> T defaultHeader(String headerName, String... headerValues) {
|
||||
this.restClientBuilder.defaultHeader(headerName, headerValues);
|
||||
return this;
|
||||
return self();
|
||||
}
|
||||
|
||||
@Override
|
||||
public RestTestClient.Builder<B> defaultHeaders(Consumer<HttpHeaders> headersConsumer) {
|
||||
public <T extends B> T defaultHeaders(Consumer<HttpHeaders> headersConsumer) {
|
||||
this.restClientBuilder.defaultHeaders(headersConsumer);
|
||||
return this;
|
||||
return self();
|
||||
}
|
||||
|
||||
@Override
|
||||
public RestTestClient.Builder<B> defaultCookie(String cookieName, String... cookieValues) {
|
||||
public <T extends B> T defaultCookie(String cookieName, String... cookieValues) {
|
||||
this.restClientBuilder.defaultCookie(cookieName, cookieValues);
|
||||
return this;
|
||||
return self();
|
||||
}
|
||||
|
||||
@Override
|
||||
public RestTestClient.Builder<B> defaultCookies(Consumer<MultiValueMap<String, String>> cookiesConsumer) {
|
||||
public <T extends B> T defaultCookies(Consumer<MultiValueMap<String, String>> cookiesConsumer) {
|
||||
this.restClientBuilder.defaultCookies(cookiesConsumer);
|
||||
return this;
|
||||
return self();
|
||||
}
|
||||
|
||||
@Override
|
||||
public RestTestClient.Builder<B> apply(Consumer<RestTestClient.Builder<B>> builderConsumer) {
|
||||
public <T extends B> T apply(Consumer<RestTestClient.Builder<B>> builderConsumer) {
|
||||
builderConsumer.accept(this);
|
||||
return this;
|
||||
return self();
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
protected <T extends B> T self() {
|
||||
return (T) this;
|
||||
}
|
||||
|
||||
protected void setClientHttpRequestFactory(ClientHttpRequestFactory requestFactory) {
|
||||
this.restClientBuilder.requestFactory(requestFactory);
|
||||
}
|
||||
|
||||
@Override
|
||||
public RestTestClient build() {
|
||||
return new DefaultRestTestClient(this.restClientBuilder);
|
||||
}
|
||||
|
||||
|
||||
static class AbstractMockMvcSetupBuilder<S extends RestTestClient.Builder<S>, M extends MockMvcBuilder>
|
||||
extends DefaultRestTestClientBuilder<S> implements RestTestClient.MockMvcSetupBuilder<S, M> {
|
||||
|
||||
private final M mockMvcBuilder;
|
||||
|
||||
public AbstractMockMvcSetupBuilder(M mockMvcBuilder) {
|
||||
this.mockMvcBuilder = mockMvcBuilder;
|
||||
}
|
||||
|
||||
public <T extends S> T configureServer(Consumer<M> consumer) {
|
||||
consumer.accept(this.mockMvcBuilder);
|
||||
return self();
|
||||
}
|
||||
|
||||
@Override
|
||||
public RestTestClient build() {
|
||||
MockMvc mockMvc = this.mockMvcBuilder.build();
|
||||
setClientHttpRequestFactory(new MockMvcClientHttpRequestFactory(mockMvc));
|
||||
return super.build();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static class DefaultStandaloneSetupBuilder extends AbstractMockMvcSetupBuilder<RestTestClient.StandaloneSetupBuilder, StandaloneMockMvcBuilder>
|
||||
implements RestTestClient.StandaloneSetupBuilder {
|
||||
|
||||
DefaultStandaloneSetupBuilder(Object... controllers) {
|
||||
super(MockMvcBuilders.standaloneSetup(controllers));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static class DefaultRouterFunctionSetupBuilder extends AbstractMockMvcSetupBuilder<RestTestClient.RouterFunctionSetupBuilder, RouterFunctionMockMvcBuilder>
|
||||
implements RestTestClient.RouterFunctionSetupBuilder {
|
||||
|
||||
DefaultRouterFunctionSetupBuilder(RouterFunction<?>... routerFunctions) {
|
||||
super(MockMvcBuilders.routerFunctions(routerFunctions));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
static class DefaultWebAppContextSetupBuilder extends AbstractMockMvcSetupBuilder<RestTestClient.WebAppContextSetupBuilder, DefaultMockMvcBuilder>
|
||||
implements RestTestClient.WebAppContextSetupBuilder {
|
||||
|
||||
DefaultWebAppContextSetupBuilder(WebApplicationContext context) {
|
||||
super(MockMvcBuilders.webAppContextSetup(context));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+34
-24
@@ -37,7 +37,6 @@ import org.springframework.test.json.JsonComparison;
|
||||
import org.springframework.test.web.servlet.MockMvc;
|
||||
import org.springframework.test.web.servlet.MockMvcBuilder;
|
||||
import org.springframework.test.web.servlet.setup.DefaultMockMvcBuilder;
|
||||
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
|
||||
import org.springframework.test.web.servlet.setup.RouterFunctionMockMvcBuilder;
|
||||
import org.springframework.test.web.servlet.setup.StandaloneMockMvcBuilder;
|
||||
import org.springframework.util.MultiValueMap;
|
||||
@@ -51,6 +50,8 @@ import org.springframework.web.util.UriBuilderFactory;
|
||||
* Client for testing web servers.
|
||||
*
|
||||
* @author Rob Worsnop
|
||||
* @author Rossen Stoyanchev
|
||||
* @since 7.0
|
||||
*/
|
||||
public interface RestTestClient {
|
||||
|
||||
@@ -126,9 +127,8 @@ public interface RestTestClient {
|
||||
* {@link org.springframework.test.web.servlet.setup.MockMvcBuilders#standaloneSetup(Object...)}
|
||||
* to initialize {@link MockMvc}.
|
||||
*/
|
||||
static MockServerBuilder<StandaloneMockMvcBuilder> standaloneSetup(Object... controllers) {
|
||||
StandaloneMockMvcBuilder builder = MockMvcBuilders.standaloneSetup(controllers);
|
||||
return new DefaultMockServerBuilder<>(builder);
|
||||
static StandaloneSetupBuilder bindToController(Object... controllers) {
|
||||
return new DefaultRestTestClientBuilder.DefaultStandaloneSetupBuilder(controllers);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -138,9 +138,8 @@ public interface RestTestClient {
|
||||
* {@link org.springframework.test.web.servlet.setup.MockMvcBuilders#routerFunctions(RouterFunction[])}
|
||||
* to initialize {@link MockMvc}.
|
||||
*/
|
||||
static MockServerBuilder<RouterFunctionMockMvcBuilder> bindToRouterFunction(RouterFunction<?>... routerFunctions) {
|
||||
RouterFunctionMockMvcBuilder builder = MockMvcBuilders.routerFunctions(routerFunctions);
|
||||
return new DefaultMockServerBuilder<>(builder);
|
||||
static RouterFunctionSetupBuilder bindToRouterFunction(RouterFunction<?>... routerFunctions) {
|
||||
return new DefaultRestTestClientBuilder.DefaultRouterFunctionSetupBuilder(routerFunctions);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -151,16 +150,15 @@ public interface RestTestClient {
|
||||
* {@link org.springframework.test.web.servlet.setup.MockMvcBuilders#webAppContextSetup(WebApplicationContext)}
|
||||
* to initialize {@code MockMvc}.
|
||||
*/
|
||||
static MockServerBuilder<DefaultMockMvcBuilder> bindToApplicationContext(WebApplicationContext context) {
|
||||
DefaultMockMvcBuilder builder = MockMvcBuilders.webAppContextSetup(context);
|
||||
return new DefaultMockServerBuilder<>(builder);
|
||||
static WebAppContextSetupBuilder bindToApplicationContext(WebApplicationContext context) {
|
||||
return new DefaultRestTestClientBuilder.DefaultWebAppContextSetupBuilder(context);
|
||||
}
|
||||
|
||||
/**
|
||||
* Begin creating a {@link RestTestClient} by providing an already
|
||||
* initialized {@link MockMvc} instance to use as the server.
|
||||
*/
|
||||
static <B extends Builder<B>> Builder<B> bindTo(MockMvc mockMvc) {
|
||||
static Builder<?> bindTo(MockMvc mockMvc) {
|
||||
ClientHttpRequestFactory requestFactory = new MockMvcClientHttpRequestFactory(mockMvc);
|
||||
return RestTestClient.bindToServer(requestFactory);
|
||||
}
|
||||
@@ -175,7 +173,7 @@ public interface RestTestClient {
|
||||
* </pre>
|
||||
* @return chained API to customize client config
|
||||
*/
|
||||
static <B extends Builder<B>> Builder<B> bindToServer() {
|
||||
static Builder<?> bindToServer() {
|
||||
return new DefaultRestTestClientBuilder<>();
|
||||
}
|
||||
|
||||
@@ -183,7 +181,7 @@ public interface RestTestClient {
|
||||
* A variant of {@link #bindToServer()} with a pre-configured request factory.
|
||||
* @return chained API to customize client config
|
||||
*/
|
||||
static <B extends Builder<B>> Builder<B> bindToServer(ClientHttpRequestFactory requestFactory) {
|
||||
static Builder<?> bindToServer(ClientHttpRequestFactory requestFactory) {
|
||||
return new DefaultRestTestClientBuilder<>(RestClient.builder().requestFactory(requestFactory));
|
||||
}
|
||||
|
||||
@@ -195,20 +193,20 @@ public interface RestTestClient {
|
||||
* {@link RestClient#create(String)
|
||||
* WebClient.create(String)}.
|
||||
*/
|
||||
Builder<B> baseUrl(String baseUrl);
|
||||
<T extends B> T baseUrl(String baseUrl);
|
||||
|
||||
/**
|
||||
* Provide a pre-configured {@link UriBuilderFactory} instance as an
|
||||
* alternative to and effectively overriding {@link #baseUrl(String)}.
|
||||
*/
|
||||
Builder<B> uriBuilderFactory(UriBuilderFactory uriBuilderFactory);
|
||||
<T extends B> T uriBuilderFactory(UriBuilderFactory uriBuilderFactory);
|
||||
|
||||
/**
|
||||
* Add the given header to all requests that haven't added it.
|
||||
* @param headerName the header name
|
||||
* @param headerValues the header values
|
||||
*/
|
||||
Builder<B> defaultHeader(String headerName, String... headerValues);
|
||||
<T extends B> T defaultHeader(String headerName, String... headerValues);
|
||||
|
||||
/**
|
||||
* Manipulate the default headers with the given consumer. The
|
||||
@@ -219,14 +217,14 @@ public interface RestTestClient {
|
||||
* @param headersConsumer a function that consumes the {@code HttpHeaders}
|
||||
* @return this builder
|
||||
*/
|
||||
Builder<B> defaultHeaders(Consumer<HttpHeaders> headersConsumer);
|
||||
<T extends B> T defaultHeaders(Consumer<HttpHeaders> headersConsumer);
|
||||
|
||||
/**
|
||||
* Add the given cookie to all requests.
|
||||
* @param cookieName the cookie name
|
||||
* @param cookieValues the cookie values
|
||||
*/
|
||||
Builder<B> defaultCookie(String cookieName, String... cookieValues);
|
||||
<T extends B> T defaultCookie(String cookieName, String... cookieValues);
|
||||
|
||||
/**
|
||||
* Manipulate the default cookies with the given consumer. The
|
||||
@@ -237,29 +235,41 @@ public interface RestTestClient {
|
||||
* @param cookiesConsumer a function that consumes the cookies map
|
||||
* @return this builder
|
||||
*/
|
||||
Builder<B> defaultCookies(Consumer<MultiValueMap<String, String>> cookiesConsumer);
|
||||
<T extends B> T defaultCookies(Consumer<MultiValueMap<String, String>> cookiesConsumer);
|
||||
|
||||
/**
|
||||
* Apply the given {@code Consumer} to this builder instance.
|
||||
* <p>This can be useful for applying pre-packaged customizations.
|
||||
* @param builderConsumer the consumer to apply
|
||||
*/
|
||||
Builder<B> apply(Consumer<Builder<B>> builderConsumer);
|
||||
<T extends B> T apply(Consumer<Builder<B>> builderConsumer);
|
||||
|
||||
/**
|
||||
* Build the {@link RestTestClient} instance.
|
||||
*/
|
||||
RestTestClient build();
|
||||
}
|
||||
|
||||
|
||||
interface MockMvcSetupBuilder<B extends Builder<B>, M extends MockMvcBuilder> extends Builder<B> {
|
||||
|
||||
<T extends B> T configureServer(Consumer<M> consumer);
|
||||
}
|
||||
|
||||
|
||||
interface MockServerBuilder<M extends MockMvcBuilder> extends Builder<MockServerBuilder<M>> {
|
||||
|
||||
MockServerBuilder<M> configureServer(Consumer<M> consumer);
|
||||
|
||||
interface StandaloneSetupBuilder extends MockMvcSetupBuilder<StandaloneSetupBuilder, StandaloneMockMvcBuilder> {
|
||||
}
|
||||
|
||||
|
||||
interface RouterFunctionSetupBuilder extends MockMvcSetupBuilder<RouterFunctionSetupBuilder, RouterFunctionMockMvcBuilder> {
|
||||
}
|
||||
|
||||
|
||||
interface WebAppContextSetupBuilder extends MockMvcSetupBuilder<WebAppContextSetupBuilder, DefaultMockMvcBuilder> {
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Specification for providing the URI of a request.
|
||||
*
|
||||
|
||||
Reference in New Issue
Block a user