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 25c8a82b61..20341cbc86 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 @@ -253,56 +253,76 @@ class DefaultWebTestClient implements WebTestClient { return toResponseSpec(this.headerSpec.exchange(publisher, elementClass)); } - private DefaultResponseSpec toResponseSpec(Mono responseMono) { - ClientResponse response = responseMono.block(getTimeout()); - ClientHttpRequest request = webTestClientConnector.claimRequest(this.requestId); - ExchangeResult> result = ExchangeResult.create(request, response); - return new DefaultResponseSpec(result, response); + private DefaultResponseSpec toResponseSpec(Mono mono) { + ClientResponse response = mono.block(getTimeout()); + ClientHttpRequest httpRequest = webTestClientConnector.claimRequest(this.requestId); + return new DefaultResponseSpec(httpRequest, response); } } - private abstract class ResponseSpecSupport { - - private final ExchangeResult> exchangeResult; + /** + * ExchangeResult that contains the live {@link ClientResponse}. + */ + private class UndecodedExchangeResult extends ExchangeResult { private final ClientResponse response; - public ResponseSpecSupport(ExchangeResult> result, ClientResponse response) { - this.exchangeResult = result; + public UndecodedExchangeResult(ClientHttpRequest httpRequest, ClientResponse response) { + super(httpRequest, response); this.response = response; } - protected ExchangeResult> getExchangeResult() { - return this.exchangeResult; + public EntityExchangeResult consumeSingle(ResolvableType elementType) { + Object body = this.response.body(toMono(elementType)).block(getTimeout()); + return new EntityExchangeResult<>(this, body); } - protected ClientResponse getResponse() { - return this.response; + public EntityExchangeResult> consumeList(ResolvableType elementType, int count) { + Flux flux = this.response.body(toFlux(elementType)); + if (count >= 0) { + flux = flux.take(count); + } + List body = flux.collectList().block(getTimeout()); + return new EntityExchangeResult<>(this, body); } - protected ExchangeResult createResultWithDecodedBody(T body) { - return ExchangeResult.withDecodedBody(this.exchangeResult, body); + public FluxExchangeResult decodeBody(ResolvableType elementType) { + Flux body = this.response.body(toFlux(elementType)); + return new FluxExchangeResult<>(this, body, elementType); } + @SuppressWarnings("unchecked") + public EntityExchangeResult> consumeMap(ResolvableType keyType, ResolvableType valueType) { + ResolvableType mapType = ResolvableType.forClassWithGenerics(Map.class, keyType, valueType); + return (EntityExchangeResult>) consumeSingle(mapType); + } + + public EntityExchangeResult consumeEmpty() { + DataBuffer buffer = this.response.body(toDataBuffers()).blockFirst(getTimeout()); + assertTrue("Expected empty body", buffer == null); + return new EntityExchangeResult<>(this, null); + } } - private class DefaultResponseSpec extends ResponseSpecSupport implements ResponseSpec { + private class DefaultResponseSpec implements ResponseSpec { + + private final UndecodedExchangeResult exchangeResult; - public DefaultResponseSpec(ExchangeResult> exchangeResult, ClientResponse response) { - super(exchangeResult, response); + public DefaultResponseSpec(ClientHttpRequest httpRequest, ClientResponse response) { + this.exchangeResult = new UndecodedExchangeResult(httpRequest, response); } @Override public StatusAssertions expectStatus() { - return new StatusAssertions(getExchangeResult(), this); + return new StatusAssertions(this.exchangeResult, this); } @Override public HeaderAssertions expectHeader() { - return new HeaderAssertions(getExchangeResult(), this); + return new HeaderAssertions(this.exchangeResult, this); } @Override @@ -312,40 +332,43 @@ class DefaultWebTestClient implements WebTestClient { @Override public TypeBodySpec expectBody(ResolvableType elementType) { - return new DefaultTypeBodySpec(this, elementType); + return new DefaultTypeBodySpec(this.exchangeResult, elementType); } @Override public BodySpec expectBody() { - return new DefaultBodySpec(this); + return new DefaultBodySpec(this.exchangeResult); } @Override - public ResponseSpec consumeWith(Consumer>> consumer) { - consumer.accept(getExchangeResult()); + public ResponseSpec consumeWith(Consumer consumer) { + consumer.accept(this.exchangeResult); return this; } @Override - public ExchangeResult> returnResult() { - return getExchangeResult(); + public ExchangeResult returnResult() { + return this.exchangeResult; } } - private class DefaultTypeBodySpec extends ResponseSpecSupport implements TypeBodySpec { + private class DefaultTypeBodySpec implements TypeBodySpec { + + private final UndecodedExchangeResult exchangeResult; private final ResolvableType elementType; - public DefaultTypeBodySpec(DefaultResponseSpec spec, ResolvableType elementType) { - super(spec.getExchangeResult(), spec.getResponse()); + public DefaultTypeBodySpec(UndecodedExchangeResult result, ResolvableType elementType) { + this.exchangeResult = result; this.elementType = elementType; } @Override public SingleValueBodySpec value() { - return new DefaultSingleValueBodySpec(this, this.elementType); + EntityExchangeResult completed = this.exchangeResult.consumeSingle(this.elementType); + return new DefaultSingleValueBodySpec(completed); } @Override @@ -354,59 +377,52 @@ class DefaultWebTestClient implements WebTestClient { } @Override - public ListBodySpec list(int elementCount) { - return new DefaultListBodySpec(this, this.elementType, elementCount); + public ListBodySpec list(int count) { + EntityExchangeResult> completed = this.exchangeResult.consumeList(this.elementType, count); + return new DefaultListBodySpec(completed); } @Override - public ExchangeResult> returnResult() { - Flux flux = getResponse().body(toFlux(this.elementType)); - return createResultWithDecodedBody(flux); + public FluxExchangeResult returnResult() { + return this.exchangeResult.decodeBody(this.elementType); } } - private class DefaultSingleValueBodySpec extends ResponseSpecSupport implements SingleValueBodySpec { + private class DefaultSingleValueBodySpec implements SingleValueBodySpec { - private final Object body; + private final EntityExchangeResult exchangeResult; - public DefaultSingleValueBodySpec(DefaultTypeBodySpec spec, ResolvableType elementType) { - super(spec.getExchangeResult(), spec.getResponse()); - this.body = getResponse().body(toMono(elementType)).block(getTimeout()); + public DefaultSingleValueBodySpec(EntityExchangeResult result) { + this.exchangeResult = result; } @Override - public ExchangeResult isEqualTo(Object expected) { - assertEquals("Response body", expected, this.body); + public EntityExchangeResult isEqualTo(T expected) { + assertEquals("Response body", expected, this.exchangeResult.getResponseBody()); return returnResult(); } @Override - @SuppressWarnings("unchecked") - public ExchangeResult returnResult() { - return createResultWithDecodedBody((T) this.body); + public EntityExchangeResult returnResult() { + return new EntityExchangeResult<>(this.exchangeResult, (T) this.exchangeResult.getResponseBody()); } } - private class DefaultListBodySpec extends ResponseSpecSupport implements ListBodySpec { + private class DefaultListBodySpec implements ListBodySpec { - private final List body; + private final EntityExchangeResult> exchangeResult; - public DefaultListBodySpec(DefaultTypeBodySpec spec, ResolvableType elementType, int elementCount) { - super(spec.getExchangeResult(), spec.getResponse()); - Flux flux = getResponse().body(toFlux(elementType)); - if (elementCount >= 0) { - flux = flux.take(elementCount); - } - this.body = flux.collectList().block(getTimeout()); + public DefaultListBodySpec(EntityExchangeResult> result) { + this.exchangeResult = result; } @Override - public ExchangeResult> isEqualTo(List expected) { - assertEquals("Response body", expected, this.body); + public EntityExchangeResult> isEqualTo(List expected) { + assertEquals("Response body", expected, this.exchangeResult.getResponseBody()); return returnResult(); } @@ -419,7 +435,7 @@ class DefaultWebTestClient implements WebTestClient { public ListBodySpec contains(Object... elements) { List elementList = Arrays.asList(elements); String message = "Response body does not contain " + elementList; - assertTrue(message, this.body.containsAll(elementList)); + assertTrue(message, this.exchangeResult.getResponseBody().containsAll(elementList)); return this; } @@ -427,30 +443,30 @@ class DefaultWebTestClient implements WebTestClient { public ListBodySpec doesNotContain(Object... elements) { List elementList = Arrays.asList(elements); String message = "Response body should have contained " + elementList; - assertTrue(message, !this.body.containsAll(Arrays.asList(elements))); + assertTrue(message, !this.exchangeResult.getResponseBody().containsAll(Arrays.asList(elements))); return this; } @Override @SuppressWarnings("unchecked") - public ExchangeResult> returnResult() { - return createResultWithDecodedBody((List) this.body); + public EntityExchangeResult> returnResult() { + return new EntityExchangeResult<>(this.exchangeResult, (List) this.exchangeResult.getResponseBody()); } } - private class DefaultBodySpec extends ResponseSpecSupport implements BodySpec { + private class DefaultBodySpec implements BodySpec { + + private final UndecodedExchangeResult exchangeResult; - public DefaultBodySpec(DefaultResponseSpec spec) { - super(spec.getExchangeResult(), spec.getResponse()); + public DefaultBodySpec(UndecodedExchangeResult result) { + this.exchangeResult = result; } @Override - public ExchangeResult isEmpty() { - DataBuffer buffer = getResponse().body(toDataBuffers()).blockFirst(getTimeout()); - assertTrue("Expected empty body", buffer == null); - return createResultWithDecodedBody(null); + public EntityExchangeResult isEmpty() { + return this.exchangeResult.consumeEmpty(); } @Override @@ -460,57 +476,61 @@ class DefaultWebTestClient implements WebTestClient { @Override public MapBodySpec map(ResolvableType keyType, ResolvableType valueType) { - return new DefaultMapBodySpec(this, keyType, valueType); + EntityExchangeResult> completed = this.exchangeResult.consumeMap(keyType, valueType); + return new DefaultMapBodySpec(completed); } } - private class DefaultMapBodySpec extends ResponseSpecSupport implements MapBodySpec { + private class DefaultMapBodySpec implements MapBodySpec { - private final Map body; + private final EntityExchangeResult> exchangeResult; - public DefaultMapBodySpec(DefaultBodySpec spec, ResolvableType keyType, ResolvableType valueType) { - super(spec.getExchangeResult(), spec.getResponse()); - ResolvableType mapType = ResolvableType.forClassWithGenerics(Map.class, keyType, valueType); - this.body = (Map) spec.getResponse().body(toMono(mapType)).block(getTimeout()); + public DefaultMapBodySpec(EntityExchangeResult> result) { + this.exchangeResult = result; } + private Map getBody() { + return this.exchangeResult.getResponseBody(); + } + @Override - public ExchangeResult> isEqualTo(Map expected) { + public EntityExchangeResult> isEqualTo(Map expected) { + assertEquals("Response body map", expected, getBody()); return returnResult(); } @Override public MapBodySpec hasSize(int size) { - assertEquals("Response body map size", size, this.body.size()); + assertEquals("Response body map size", size, getBody().size()); return this; } @Override public MapBodySpec contains(Object key, Object value) { - assertEquals("Response body map value for key " + key, value, this.body.get(key)); + assertEquals("Response body map value for key " + key, value, getBody().get(key)); return this; } @Override public MapBodySpec containsKeys(Object... keys) { - List missing = Arrays.stream(keys).filter(k -> !this.body.containsKey(k)).collect(toList()); + List missing = Arrays.stream(keys).filter(k -> !getBody().containsKey(k)).collect(toList()); assertTrue("Response body map does not contain keys " + missing, missing.isEmpty()); return this; } @Override public MapBodySpec containsValues(Object... values) { - List missing = Arrays.stream(values).filter(v -> !this.body.containsValue(v)).collect(toList()); + List missing = Arrays.stream(values).filter(v -> !getBody().containsValue(v)).collect(toList()); assertTrue("Response body map does not contain values " + missing, missing.isEmpty()); return this; } @Override @SuppressWarnings("unchecked") - public ExchangeResult> returnResult() { - return createResultWithDecodedBody((Map) this.body); + public EntityExchangeResult> returnResult() { + return new EntityExchangeResult<>(this.exchangeResult, (Map) getBody()); } } diff --git a/spring-test/src/main/java/org/springframework/test/web/reactive/server/EntityExchangeResult.java b/spring-test/src/main/java/org/springframework/test/web/reactive/server/EntityExchangeResult.java new file mode 100644 index 0000000000..32a619f8b2 --- /dev/null +++ b/spring-test/src/main/java/org/springframework/test/web/reactive/server/EntityExchangeResult.java @@ -0,0 +1,50 @@ +/* + * Copyright 2002-2017 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 + * + * http://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.reactive.server; + +/** + * {@code ExchangeResult} variant with the response body fully extracted to a + * representation of type {@code }. + * + * @param the response body type + * + * @author Rossen Stoyanchev + * @since 5.0 + */ +public class EntityExchangeResult extends ExchangeResult { + + private final T body; + + + EntityExchangeResult(ExchangeResult exchange, T body) { + super(exchange); + this.body = body; + } + + + /** + * Return the body extracted from the response. + */ + public T getResponseBody() { + return this.body; + } + + @Override + protected String formatResponseBody() { + return this.body.toString(); + } + +} diff --git a/spring-test/src/main/java/org/springframework/test/web/reactive/server/ExchangeResult.java b/spring-test/src/main/java/org/springframework/test/web/reactive/server/ExchangeResult.java index 24318aee1b..e5f5308e57 100644 --- a/spring-test/src/main/java/org/springframework/test/web/reactive/server/ExchangeResult.java +++ b/spring-test/src/main/java/org/springframework/test/web/reactive/server/ExchangeResult.java @@ -18,27 +18,27 @@ package org.springframework.test.web.reactive.server; import java.net.URI; import java.util.stream.Collectors; -import reactor.core.publisher.Flux; - -import org.springframework.core.io.buffer.DataBuffer; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpMethod; import org.springframework.http.HttpStatus; import org.springframework.http.client.reactive.ClientHttpRequest; import org.springframework.web.reactive.function.client.ClientResponse; -import static org.springframework.web.reactive.function.BodyExtractors.toDataBuffers; - /** - * Container for request and response details from an exchange performed - * through {@link WebTestClient}. + * Container for the result of an exchange through the {@link WebTestClient}. * - * @param the type of the response body + *

This type only exposes the status and response headers that are available + * when the {@link ClientResponse} is first received and before the response + * body has been consumed. + * + *

The sub-classes {@link EntityExchangeResult} and {@link FluxExchangeResult} + * expose further information about the response body and are returned only + * after the test client has been used to decode and consume the response. * * @author Rossen Stoyanchev * @since 5.0 */ -public class ExchangeResult { +public class ExchangeResult { private final HttpMethod method; @@ -50,84 +50,59 @@ public class ExchangeResult { private final HttpHeaders responseHeaders; - private final T responseBody; + ExchangeResult(ClientHttpRequest request, ClientResponse response) { + this.method = request.getMethod(); + this.url = request.getURI(); + this.requestHeaders = request.getHeaders(); + this.status = response.statusCode(); + this.responseHeaders = response.headers().asHttpHeaders(); + } - /** - * Package private constructor. - */ - ExchangeResult(HttpMethod method, URI url, HttpHeaders requestHeaders, HttpStatus status, - HttpHeaders responseHeaders, T responseBody) { - - this.method = method; - this.url = url; - this.requestHeaders = requestHeaders; - this.status = status; - this.responseHeaders = responseHeaders; - this.responseBody = responseBody; + ExchangeResult(ExchangeResult exchange) { + this.method = exchange.getMethod(); + this.url = exchange.getUrl(); + this.requestHeaders = exchange.getRequestHeaders(); + this.status = exchange.getStatus(); + this.responseHeaders = exchange.getResponseHeaders(); } /** - * Return the request method of the exchange. + * Return the method of the request. */ public HttpMethod getMethod() { return this.method; } /** - * Return the URL of the exchange. + * Return the request headers that were sent to the server. */ public URI getUrl() { return this.url; } /** - * Return the request headers of the exchange. + * Return the request headers sent to the server. */ public HttpHeaders getRequestHeaders() { return this.requestHeaders; } /** - * Return the response status. + * Return the status of the executed request. */ public HttpStatus getStatus() { return this.status; } /** - * Return the response headers. + * Return the response headers received from the server. */ public HttpHeaders getResponseHeaders() { return this.responseHeaders; } - /** - * Return the decoded response body. - */ - public T getResponseBody() { - return this.responseBody; - } - - - /** - * Create from ClientHttpRequest and ClientResponse (body not yet consumed). - */ - static ExchangeResult> create(ClientHttpRequest request, ClientResponse response) { - return new ExchangeResult<>(request.getMethod(), request.getURI(), request.getHeaders(), - response.statusCode(), response.headers().asHttpHeaders(), - response.body(toDataBuffers())); - } - - /** - * Re-create with decoded body (possibly still not consumed). - */ - static ExchangeResult withDecodedBody(ExchangeResult result, T body) { - return new ExchangeResult<>(result.getMethod(), result.getUrl(), result.getRequestHeaders(), - result.getStatus(), result.getResponseHeaders(), body); - } - @Override public String toString() { @@ -135,10 +110,10 @@ public class ExchangeResult { return "\n\n" + formatValue("Request", this.method + " " + getUrl()) + formatValue("Status", status + " " + status.getReasonPhrase()) + - formatHeading("Response Headers") + - formatHeaders(this.responseHeaders) + - formatHeading("Request Headers") + - formatHeaders(this.requestHeaders); + formatHeading("Response Headers") + formatHeaders(this.responseHeaders) + + formatHeading("Request Headers") + formatHeaders(this.requestHeaders) + + "\n" + + formatValue("Response Body", formatResponseBody()); } private String formatHeading(String heading) { @@ -155,4 +130,8 @@ public class ExchangeResult { .collect(Collectors.joining()); } + protected String formatResponseBody() { + return "Not read yet"; + } + } diff --git a/spring-test/src/main/java/org/springframework/test/web/reactive/server/FluxExchangeResult.java b/spring-test/src/main/java/org/springframework/test/web/reactive/server/FluxExchangeResult.java new file mode 100644 index 0000000000..c90a4d2c3b --- /dev/null +++ b/spring-test/src/main/java/org/springframework/test/web/reactive/server/FluxExchangeResult.java @@ -0,0 +1,56 @@ +/* + * Copyright 2002-2017 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 + * + * http://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.reactive.server; + +import reactor.core.publisher.Flux; + +import org.springframework.core.ResolvableType; + +/** + * {@code ExchangeResult} variant with the response body as a {@code Flux}. + * + * @param the type of elements in the response body + * + * @author Rossen Stoyanchev + * @since 5.0 + */ +public class FluxExchangeResult extends ExchangeResult { + + private final Flux body; + + private final ResolvableType elementType; + + + FluxExchangeResult(ExchangeResult exchange, Flux body, ResolvableType elementType) { + super(exchange); + this.body = body; + this.elementType = elementType; + } + + + /** + * Return the {@code Flux} of elements decoded from the response body. + */ + public Flux getResponseBody() { + return this.body; + } + + @Override + protected String formatResponseBody() { + return "Flux<" + this.elementType.toString() + ">"; + } + +} diff --git a/spring-test/src/main/java/org/springframework/test/web/reactive/server/HeaderAssertions.java b/spring-test/src/main/java/org/springframework/test/web/reactive/server/HeaderAssertions.java index e7269511ed..4a79210ead 100644 --- a/spring-test/src/main/java/org/springframework/test/web/reactive/server/HeaderAssertions.java +++ b/spring-test/src/main/java/org/springframework/test/web/reactive/server/HeaderAssertions.java @@ -37,14 +37,14 @@ import static org.springframework.test.util.AssertionErrors.assertTrue; */ public class HeaderAssertions { - private final ExchangeResult exchangeResult; + private final ExchangeResult exchangeResult; private final WebTestClient.ResponseSpec responseSpec; - HeaderAssertions(ExchangeResult exchangeResult, WebTestClient.ResponseSpec responseSpec) { - this.exchangeResult = exchangeResult; - this.responseSpec = responseSpec; + HeaderAssertions(ExchangeResult result, WebTestClient.ResponseSpec spec) { + this.exchangeResult = result; + this.responseSpec = spec; } diff --git a/spring-test/src/main/java/org/springframework/test/web/reactive/server/StatusAssertions.java b/spring-test/src/main/java/org/springframework/test/web/reactive/server/StatusAssertions.java index 5e5a24cbab..e53229db00 100644 --- a/spring-test/src/main/java/org/springframework/test/web/reactive/server/StatusAssertions.java +++ b/spring-test/src/main/java/org/springframework/test/web/reactive/server/StatusAssertions.java @@ -29,14 +29,14 @@ import static org.springframework.test.util.AssertionErrors.assertEquals; @SuppressWarnings("unused") public class StatusAssertions { - private final ExchangeResult exchangeResult; + private final ExchangeResult exchangeResult; private final WebTestClient.ResponseSpec responseSpec; - StatusAssertions(ExchangeResult exchangeResult, WebTestClient.ResponseSpec responseSpec) { - this.exchangeResult = exchangeResult; - this.responseSpec = responseSpec; + StatusAssertions(ExchangeResult result, WebTestClient.ResponseSpec spec) { + this.exchangeResult = result; + this.responseSpec = spec; } 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 ed7d97b00f..60cd6599b7 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 @@ -25,11 +25,9 @@ import java.util.function.Consumer; import java.util.function.Function; import org.reactivestreams.Publisher; -import reactor.core.publisher.Flux; import org.springframework.context.ApplicationContext; import org.springframework.core.ResolvableType; -import org.springframework.core.io.buffer.DataBuffer; import org.springframework.format.FormatterRegistry; import org.springframework.http.HttpHeaders; import org.springframework.http.MediaType; @@ -464,7 +462,7 @@ public interface WebTestClient { /** * Assertions on the body of the response extracted to one or more - * elements of the given type. + * representations of the given type. */ TypeBodySpec expectBody(Class elementType); @@ -474,24 +472,23 @@ public interface WebTestClient { TypeBodySpec expectBody(ResolvableType elementType); /** - * Access to additional assertions on the response body -- - * isEmpty, map, and others. + * Other assertions on the response body -- isEmpty, map, etc. */ BodySpec expectBody(); /** - * Consume the {@link ExchangeResult} and continue with expectations. - * The {@code ExchangeResult} is parameterized with data buffers since - * the body is not yet consumed nor decoded at this level. + * Consume request and response details of the exchange. Only status + * response headers are available at this stage before one of the + * {@code expectBody} methods is used. */ - ResponseSpec consumeWith(Consumer>> consumer); + ResponseSpec consumeWith(Consumer consumer); /** - * Return a container for the result of the exchange. The returned - * {@code ExchangeResult} is parameterized with data buffers since - * the body is not yet consumed nor decoded at this level. + * Return the request and response details of the exchange. Only status + * and response headers are available at this stage before one of the + * {@code expectBody} methods is used. */ - ExchangeResult> returnResult(); + ExchangeResult returnResult(); } /** @@ -500,25 +497,26 @@ public interface WebTestClient { interface TypeBodySpec { /** - * Extract a single value from the response. + * Extract a single representations from the response. */ SingleValueBodySpec value(); /** - * Extract a list of values from the response. + * Extract a list of representations from the response. */ ListBodySpec list(); /** - * Extract a list of values consuming the first N elements. + * Extract a list of representations consuming the first N elements. */ ListBodySpec list(int elementCount); /** - * Return a container for the result of the exchange parameterized with - * the {@code Flux} of decoded objects (not yet consumed). + * Return request and response details from the exchange including the + * response body as a {@code Flux} and available for example for use + * with a {@code StepVerifier} from Project Reactor. */ - ExchangeResult> returnResult(); + FluxExchangeResult returnResult(); } /** @@ -529,13 +527,13 @@ public interface WebTestClient { /** * Assert the extracted body is equal to the given value. */ - ExchangeResult isEqualTo(Object expected); + EntityExchangeResult isEqualTo(T expected); /** - * Return a container for the result of the exchange parameterized with - * the extracted response entity. + * Return request and response details from the exchange including the + * extracted response body. */ - ExchangeResult returnResult(); + EntityExchangeResult returnResult(); } /** @@ -546,7 +544,7 @@ public interface WebTestClient { /** * Assert the extracted body is equal to the given list. */ - ExchangeResult> isEqualTo(List expected); + EntityExchangeResult> isEqualTo(List expected); /** * Assert the extracted list of values is of the given size. @@ -567,10 +565,10 @@ public interface WebTestClient { ListBodySpec doesNotContain(Object... elements); /** - * Return a container for the result of the exchange parameterized with - * the extracted list of response entities. + * Return request and response details from the exchange including the + * extracted response body. */ - ExchangeResult> returnResult(); + EntityExchangeResult> returnResult(); } /** @@ -580,9 +578,9 @@ public interface WebTestClient { /** * Consume the body and verify it is empty. - * @return container for the result of the exchange + * @return request and response details from the exchange */ - ExchangeResult isEmpty(); + EntityExchangeResult isEmpty(); /** * Extract the response body as a Map with the given key and value type. @@ -604,7 +602,7 @@ public interface WebTestClient { /** * Assert the extracted map is equal to the given list of elements. */ - ExchangeResult> isEqualTo(Map expected); + EntityExchangeResult> isEqualTo(Map expected); /** * Assert the extracted map has the given size. @@ -632,9 +630,10 @@ public interface WebTestClient { MapBodySpec containsValues(Object... values); /** - * Return a container for the result of the exchange. + * Return request and response details from the exchange including the + * extracted response body. */ - ExchangeResult> returnResult(); + EntityExchangeResult> returnResult(); } } 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 9ef604a387..009e610394 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 @@ -31,7 +31,7 @@ import reactor.test.StepVerifier; import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; -import org.springframework.test.web.reactive.server.ExchangeResult; +import org.springframework.test.web.reactive.server.FluxExchangeResult; import org.springframework.test.web.reactive.server.WebTestClient; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; @@ -101,7 +101,7 @@ public class ResponseEntityTests { @Test public void entityStream() throws Exception { - ExchangeResult> result = this.client.get() + FluxExchangeResult result = this.client.get() .uri("/persons") .accept(TEXT_EVENT_STREAM) .exchange()