Avoid required uri when using WebTestClient w/ base url
This commit makes the `uri` step of the WebTestClient optional, so that users who have specified a base URL during WebClient config do not need to provide an empty one (i.e. `url("")`). Issue: SPR-15695
This commit is contained in:
parent
3232cb6260
commit
5f2d2b21d9
|
@ -93,38 +93,47 @@ class DefaultWebTestClient implements WebTestClient {
|
|||
|
||||
|
||||
@Override
|
||||
public UriSpec<RequestHeadersSpec<?>> get() {
|
||||
return toUriSpec(wc -> wc.method(HttpMethod.GET));
|
||||
public RequestHeadersUriSpec<?> get() {
|
||||
return methodInternal(HttpMethod.GET);
|
||||
}
|
||||
|
||||
@Override
|
||||
public UriSpec<RequestHeadersSpec<?>> head() {
|
||||
return toUriSpec(wc -> wc.method(HttpMethod.HEAD));
|
||||
public RequestHeadersUriSpec<?> head() {
|
||||
return methodInternal(HttpMethod.HEAD);
|
||||
}
|
||||
|
||||
@Override
|
||||
public UriSpec<RequestBodySpec> post() {
|
||||
return toUriSpec(wc -> wc.method(HttpMethod.POST));
|
||||
public RequestBodyUriSpec post() {
|
||||
return methodInternal(HttpMethod.POST);
|
||||
}
|
||||
|
||||
@Override
|
||||
public UriSpec<RequestBodySpec> put() {
|
||||
return toUriSpec(wc -> wc.method(HttpMethod.PUT));
|
||||
public RequestBodyUriSpec put() {
|
||||
return methodInternal(HttpMethod.PUT);
|
||||
}
|
||||
|
||||
@Override
|
||||
public UriSpec<RequestBodySpec> patch() {
|
||||
return toUriSpec(wc -> wc.method(HttpMethod.PATCH));
|
||||
public RequestBodyUriSpec patch() {
|
||||
return methodInternal(HttpMethod.PATCH);
|
||||
}
|
||||
|
||||
@Override
|
||||
public UriSpec<RequestHeadersSpec<?>> delete() {
|
||||
return toUriSpec(wc -> wc.method(HttpMethod.DELETE));
|
||||
public RequestHeadersUriSpec<?> delete() {
|
||||
return methodInternal(HttpMethod.DELETE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public UriSpec<RequestHeadersSpec<?>> options() {
|
||||
return toUriSpec(wc -> wc.method(HttpMethod.OPTIONS));
|
||||
public RequestHeadersUriSpec<?> options() {
|
||||
return methodInternal(HttpMethod.OPTIONS);
|
||||
}
|
||||
|
||||
@Override
|
||||
public RequestBodyUriSpec method(HttpMethod method) {
|
||||
return methodInternal(method);
|
||||
}
|
||||
|
||||
private RequestBodyUriSpec methodInternal(HttpMethod method) {
|
||||
return new DefaultRequestBodyUriSpec(this.webClient.method(method));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -132,60 +141,50 @@ class DefaultWebTestClient implements WebTestClient {
|
|||
return this.builder;
|
||||
}
|
||||
|
||||
private <S extends RequestHeadersSpec<?>> UriSpec<S> toUriSpec(
|
||||
Function<WebClient, WebClient.UriSpec<WebClient.RequestBodySpec>> function) {
|
||||
|
||||
return new DefaultUriSpec<>(function.apply(this.webClient));
|
||||
}
|
||||
private class DefaultRequestBodyUriSpec implements RequestBodyUriSpec {
|
||||
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private class DefaultUriSpec<S extends RequestHeadersSpec<?>> implements UriSpec<S> {
|
||||
|
||||
private final WebClient.UriSpec<WebClient.RequestBodySpec> uriSpec;
|
||||
|
||||
|
||||
DefaultUriSpec(WebClient.UriSpec<WebClient.RequestBodySpec> spec) {
|
||||
this.uriSpec = spec;
|
||||
}
|
||||
|
||||
@Override
|
||||
public S uri(URI uri) {
|
||||
return (S) new DefaultRequestBodySpec(this.uriSpec.uri(uri), null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public S uri(String uriTemplate, Object... uriVariables) {
|
||||
return (S) new DefaultRequestBodySpec(this.uriSpec.uri(uriTemplate, uriVariables), uriTemplate);
|
||||
}
|
||||
|
||||
@Override
|
||||
public S uri(String uriTemplate, Map<String, ?> uriVariables) {
|
||||
return (S) new DefaultRequestBodySpec(this.uriSpec.uri(uriTemplate, uriVariables), uriTemplate);
|
||||
}
|
||||
|
||||
@Override
|
||||
public S uri(Function<UriBuilder, URI> uriBuilder) {
|
||||
return (S) new DefaultRequestBodySpec(this.uriSpec.uri(uriBuilder), null);
|
||||
}
|
||||
}
|
||||
|
||||
private class DefaultRequestBodySpec implements RequestBodySpec {
|
||||
|
||||
private final WebClient.RequestBodySpec bodySpec;
|
||||
private final WebClient.RequestBodyUriSpec bodySpec;
|
||||
|
||||
@Nullable
|
||||
private final String uriTemplate;
|
||||
private String uriTemplate;
|
||||
|
||||
private final String requestId;
|
||||
|
||||
DefaultRequestBodySpec(WebClient.RequestBodySpec spec, @Nullable String uriTemplate) {
|
||||
DefaultRequestBodyUriSpec(WebClient.RequestBodyUriSpec spec) {
|
||||
this.bodySpec = spec;
|
||||
this.uriTemplate = uriTemplate;
|
||||
this.requestId = String.valueOf(requestIndex.incrementAndGet());
|
||||
this.bodySpec.header(WebTestClient.WEBTESTCLIENT_REQUEST_ID, this.requestId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public RequestBodySpec uri(String uriTemplate, Object... uriVariables) {
|
||||
this.bodySpec.uri(uriTemplate, uriVariables);
|
||||
this.uriTemplate = uriTemplate;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public RequestBodySpec uri(String uriTemplate, Map<String, ?> uriVariables) {
|
||||
this.bodySpec.uri(uriTemplate, uriVariables);
|
||||
this.uriTemplate = uriTemplate;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public RequestBodySpec uri(Function<UriBuilder, URI> uriFunction) {
|
||||
this.bodySpec.uri(uriFunction);
|
||||
this.uriTemplate = null;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public RequestBodySpec uri(URI uri) {
|
||||
this.bodySpec.uri(uri);
|
||||
this.uriTemplate = null;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public RequestBodySpec header(String headerName, String... headerValues) {
|
||||
this.bodySpec.header(headerName, headerValues);
|
||||
|
|
|
@ -31,6 +31,7 @@ import org.springframework.context.ApplicationContext;
|
|||
import org.springframework.core.ParameterizedTypeReference;
|
||||
import org.springframework.format.FormatterRegistry;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.client.reactive.ClientHttpRequest;
|
||||
import org.springframework.http.codec.ServerCodecConfigurer;
|
||||
|
@ -89,43 +90,50 @@ public interface WebTestClient {
|
|||
* Prepare an HTTP GET request.
|
||||
* @return a spec for specifying the target URL
|
||||
*/
|
||||
UriSpec<RequestHeadersSpec<?>> get();
|
||||
RequestHeadersUriSpec<?> get();
|
||||
|
||||
/**
|
||||
* Prepare an HTTP HEAD request.
|
||||
* @return a spec for specifying the target URL
|
||||
*/
|
||||
UriSpec<RequestHeadersSpec<?>> head();
|
||||
RequestHeadersUriSpec<?> head();
|
||||
|
||||
/**
|
||||
* Prepare an HTTP POST request.
|
||||
* @return a spec for specifying the target URL
|
||||
*/
|
||||
UriSpec<RequestBodySpec> post();
|
||||
RequestBodyUriSpec post();
|
||||
|
||||
/**
|
||||
* Prepare an HTTP PUT request.
|
||||
* @return a spec for specifying the target URL
|
||||
*/
|
||||
UriSpec<RequestBodySpec> put();
|
||||
RequestBodyUriSpec put();
|
||||
|
||||
/**
|
||||
* Prepare an HTTP PATCH request.
|
||||
* @return a spec for specifying the target URL
|
||||
*/
|
||||
UriSpec<RequestBodySpec> patch();
|
||||
RequestBodyUriSpec patch();
|
||||
|
||||
/**
|
||||
* Prepare an HTTP DELETE request.
|
||||
* @return a spec for specifying the target URL
|
||||
*/
|
||||
UriSpec<RequestHeadersSpec<?>> delete();
|
||||
RequestHeadersUriSpec<?> delete();
|
||||
|
||||
/**
|
||||
* Prepare an HTTP OPTIONS request.
|
||||
* @return a spec for specifying the target URL
|
||||
*/
|
||||
UriSpec<RequestHeadersSpec<?>> options();
|
||||
RequestHeadersUriSpec<?> options();
|
||||
|
||||
/**
|
||||
* Prepare a request for the specified {@code HttpMethod}.
|
||||
* @return a spec for specifying the target URL
|
||||
*/
|
||||
RequestBodyUriSpec method(HttpMethod method);
|
||||
|
||||
|
||||
|
||||
/**
|
||||
|
@ -152,7 +160,7 @@ public interface WebTestClient {
|
|||
* detected from an {@link ApplicationContext} such as
|
||||
* {@code @EnableWebFlux} Java config and annotated controller Spring beans.
|
||||
* @param applicationContext the context
|
||||
* @return the {@link WebTestClient} builder
|
||||
* @return the {@code WebTestClient} builder
|
||||
* @see org.springframework.web.reactive.config.EnableWebFlux
|
||||
*/
|
||||
static MockServerSpec<?> bindToApplicationContext(ApplicationContext applicationContext) {
|
||||
|
@ -162,7 +170,7 @@ public interface WebTestClient {
|
|||
/**
|
||||
* Integration testing without a server targeting WebFlux functional endpoints.
|
||||
* @param routerFunction the RouterFunction to test
|
||||
* @return the {@link WebTestClient} builder
|
||||
* @return the {@code WebTestClient} builder
|
||||
*/
|
||||
static RouterFunctionSpec bindToRouterFunction(RouterFunction<?> routerFunction) {
|
||||
return new DefaultRouterFunctionSpec(routerFunction);
|
||||
|
@ -171,7 +179,7 @@ public interface WebTestClient {
|
|||
/**
|
||||
* Integration testing with a "mock" server targeting the given WebHandler.
|
||||
* @param webHandler the handler to test
|
||||
* @return the {@link WebTestClient} builder
|
||||
* @return the {@code WebTestClient} builder
|
||||
*/
|
||||
static MockServerSpec<?> bindToWebHandler(WebHandler webHandler) {
|
||||
return new DefaultMockServerSpec(webHandler);
|
||||
|
@ -179,7 +187,7 @@ public interface WebTestClient {
|
|||
|
||||
/**
|
||||
* Complete end-to-end integration tests with actual requests to a running server.
|
||||
* @return the {@link WebTestClient} builder
|
||||
* @return the {@code WebTestClient} builder
|
||||
*/
|
||||
static Builder bindToServer() {
|
||||
return new DefaultWebTestClientBuilder();
|
||||
|
@ -580,6 +588,14 @@ public interface WebTestClient {
|
|||
|
||||
}
|
||||
|
||||
interface RequestHeadersUriSpec<S extends RequestHeadersSpec<S>>
|
||||
extends UriSpec<S>, RequestHeadersSpec<S> {
|
||||
}
|
||||
|
||||
interface RequestBodyUriSpec extends RequestBodySpec, RequestHeadersUriSpec<RequestBodySpec> {
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Spec for declaring expectations on the response.
|
||||
*/
|
||||
|
|
|
@ -51,12 +51,15 @@ import static org.springframework.http.MediaType.TEXT_EVENT_STREAM;
|
|||
*/
|
||||
public class ResponseEntityTests {
|
||||
|
||||
private final WebTestClient client = WebTestClient.bindToController(new PersonController()).build();
|
||||
private final WebTestClient client = WebTestClient.bindToController(new PersonController())
|
||||
.configureClient()
|
||||
.baseUrl("/persons")
|
||||
.build();
|
||||
|
||||
|
||||
@Test
|
||||
public void entity() throws Exception {
|
||||
this.client.get().uri("/persons/John")
|
||||
this.client.get().uri("/John")
|
||||
.exchange()
|
||||
.expectStatus().isOk()
|
||||
.expectHeader().contentType(MediaType.APPLICATION_JSON_UTF8)
|
||||
|
@ -65,7 +68,7 @@ public class ResponseEntityTests {
|
|||
|
||||
@Test
|
||||
public void entityWithConsumer() throws Exception {
|
||||
this.client.get().uri("/persons/John")
|
||||
this.client.get().uri("/John")
|
||||
.exchange()
|
||||
.expectStatus().isOk()
|
||||
.expectHeader().contentType(MediaType.APPLICATION_JSON_UTF8)
|
||||
|
@ -79,7 +82,7 @@ public class ResponseEntityTests {
|
|||
List<Person> expected = Arrays.asList(
|
||||
new Person("Jane"), new Person("Jason"), new Person("John"));
|
||||
|
||||
this.client.get().uri("/persons")
|
||||
this.client.get()
|
||||
.exchange()
|
||||
.expectStatus().isOk()
|
||||
.expectHeader().contentType(MediaType.APPLICATION_JSON_UTF8)
|
||||
|
@ -94,7 +97,7 @@ public class ResponseEntityTests {
|
|||
map.put("Jason", new Person("Jason"));
|
||||
map.put("John", new Person("John"));
|
||||
|
||||
this.client.get().uri("/persons?map=true")
|
||||
this.client.get().uri("?map=true")
|
||||
.exchange()
|
||||
.expectStatus().isOk()
|
||||
.expectBody(new ParameterizedTypeReference<Map<String, Person>>() {}).isEqualTo(map);
|
||||
|
@ -104,7 +107,6 @@ public class ResponseEntityTests {
|
|||
public void entityStream() throws Exception {
|
||||
|
||||
FluxExchangeResult<Person> result = this.client.get()
|
||||
.uri("/persons")
|
||||
.accept(TEXT_EVENT_STREAM)
|
||||
.exchange()
|
||||
.expectStatus().isOk()
|
||||
|
@ -121,7 +123,7 @@ public class ResponseEntityTests {
|
|||
|
||||
@Test
|
||||
public void postEntity() throws Exception {
|
||||
this.client.post().uri("/persons")
|
||||
this.client.post()
|
||||
.syncBody(new Person("John"))
|
||||
.exchange()
|
||||
.expectStatus().isCreated()
|
||||
|
|
Loading…
Reference in New Issue