diff --git a/spring-test/src/main/java/org/springframework/test/web/reactive/server/DefaultWebTestClient.java b/spring-test/src/main/java/org/springframework/test/web/reactive/server/DefaultWebTestClient.java index c394771a0e..081afad4ee 100644 --- a/spring-test/src/main/java/org/springframework/test/web/reactive/server/DefaultWebTestClient.java +++ b/spring-test/src/main/java/org/springframework/test/web/reactive/server/DefaultWebTestClient.java @@ -93,38 +93,47 @@ class DefaultWebTestClient implements WebTestClient { @Override - public UriSpec> get() { - return toUriSpec(wc -> wc.method(HttpMethod.GET)); + public RequestHeadersUriSpec get() { + return methodInternal(HttpMethod.GET); } @Override - public UriSpec> head() { - return toUriSpec(wc -> wc.method(HttpMethod.HEAD)); + public RequestHeadersUriSpec head() { + return methodInternal(HttpMethod.HEAD); } @Override - public UriSpec post() { - return toUriSpec(wc -> wc.method(HttpMethod.POST)); + public RequestBodyUriSpec post() { + return methodInternal(HttpMethod.POST); } @Override - public UriSpec put() { - return toUriSpec(wc -> wc.method(HttpMethod.PUT)); + public RequestBodyUriSpec put() { + return methodInternal(HttpMethod.PUT); } @Override - public UriSpec patch() { - return toUriSpec(wc -> wc.method(HttpMethod.PATCH)); + public RequestBodyUriSpec patch() { + return methodInternal(HttpMethod.PATCH); } @Override - public UriSpec> delete() { - return toUriSpec(wc -> wc.method(HttpMethod.DELETE)); + public RequestHeadersUriSpec delete() { + return methodInternal(HttpMethod.DELETE); } @Override - public UriSpec> 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 > UriSpec toUriSpec( - Function> function) { - return new DefaultUriSpec<>(function.apply(this.webClient)); - } + private class DefaultRequestBodyUriSpec implements RequestBodyUriSpec { - - @SuppressWarnings("unchecked") - private class DefaultUriSpec> implements UriSpec { - - private final WebClient.UriSpec uriSpec; - - - DefaultUriSpec(WebClient.UriSpec 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 uriVariables) { - return (S) new DefaultRequestBodySpec(this.uriSpec.uri(uriTemplate, uriVariables), uriTemplate); - } - - @Override - public S uri(Function 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 uriVariables) { + this.bodySpec.uri(uriTemplate, uriVariables); + this.uriTemplate = uriTemplate; + return this; + } + + @Override + public RequestBodySpec uri(Function 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); diff --git a/spring-test/src/main/java/org/springframework/test/web/reactive/server/WebTestClient.java b/spring-test/src/main/java/org/springframework/test/web/reactive/server/WebTestClient.java index 04276b820b..373f5eaa82 100644 --- a/spring-test/src/main/java/org/springframework/test/web/reactive/server/WebTestClient.java +++ b/spring-test/src/main/java/org/springframework/test/web/reactive/server/WebTestClient.java @@ -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> get(); + RequestHeadersUriSpec get(); /** * Prepare an HTTP HEAD request. * @return a spec for specifying the target URL */ - UriSpec> head(); + RequestHeadersUriSpec head(); /** * Prepare an HTTP POST request. * @return a spec for specifying the target URL */ - UriSpec post(); + RequestBodyUriSpec post(); /** * Prepare an HTTP PUT request. * @return a spec for specifying the target URL */ - UriSpec put(); + RequestBodyUriSpec put(); /** * Prepare an HTTP PATCH request. * @return a spec for specifying the target URL */ - UriSpec patch(); + RequestBodyUriSpec patch(); /** * Prepare an HTTP DELETE request. * @return a spec for specifying the target URL */ - UriSpec> delete(); + RequestHeadersUriSpec delete(); /** * Prepare an HTTP OPTIONS request. * @return a spec for specifying the target URL */ - UriSpec> 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> + extends UriSpec, RequestHeadersSpec { + } + + interface RequestBodyUriSpec extends RequestBodySpec, RequestHeadersUriSpec { + } + + /** * Spec for declaring expectations on the response. */ diff --git a/spring-test/src/test/java/org/springframework/test/web/reactive/server/samples/ResponseEntityTests.java b/spring-test/src/test/java/org/springframework/test/web/reactive/server/samples/ResponseEntityTests.java index b7ec6ee230..c7c14571d5 100644 --- a/spring-test/src/test/java/org/springframework/test/web/reactive/server/samples/ResponseEntityTests.java +++ b/spring-test/src/test/java/org/springframework/test/web/reactive/server/samples/ResponseEntityTests.java @@ -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 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>() {}).isEqualTo(map); @@ -104,7 +107,6 @@ public class ResponseEntityTests { public void entityStream() throws Exception { FluxExchangeResult 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()