Improve access to raw content in WebTestClient
If the content has not been consumed, cause it to be produced, and wait for a certain amount of time before giving up, so the raw content can be made available. This can occur when: 1) In a mock server scenario the Flux representing the client request content is passed directly to the mock server request, but is never consumed because of an error before the body is read. 2) Test obtains FluxExchangeResult (e.g. for streaming) but instead of consuming the Flux, it calls getResponseBodyContent() instead. Issue: SPR-17363
This commit is contained in:
@@ -17,6 +17,7 @@
|
||||
package org.springframework.test.web.reactive.server;
|
||||
|
||||
import java.net.URI;
|
||||
import java.time.Duration;
|
||||
import java.time.ZoneId;
|
||||
import java.time.ZonedDateTime;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
@@ -257,7 +258,7 @@ public class HeaderAssertionTests {
|
||||
MonoProcessor<byte[]> emptyContent = MonoProcessor.create();
|
||||
emptyContent.onComplete();
|
||||
|
||||
ExchangeResult result = new ExchangeResult(request, response, emptyContent, emptyContent, null);
|
||||
ExchangeResult result = new ExchangeResult(request, response, emptyContent, emptyContent, Duration.ZERO, null);
|
||||
return new HeaderAssertions(result, mock(WebTestClient.ResponseSpec.class));
|
||||
}
|
||||
|
||||
|
||||
@@ -18,17 +18,19 @@ package org.springframework.test.web.reactive.server;
|
||||
import java.util.Arrays;
|
||||
|
||||
import org.junit.Test;
|
||||
import reactor.core.publisher.Flux;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
import org.springframework.core.io.buffer.DataBuffer;
|
||||
import org.springframework.core.io.buffer.DefaultDataBufferFactory;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.ResponseCookie;
|
||||
import org.springframework.http.server.reactive.ServerHttpResponse;
|
||||
|
||||
import static java.nio.charset.StandardCharsets.UTF_8;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static java.nio.charset.StandardCharsets.*;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
/**
|
||||
* Test scenarios involving a mock server.
|
||||
@@ -38,7 +40,7 @@ public class MockServerTests {
|
||||
|
||||
|
||||
@Test // SPR-15674 (in comments)
|
||||
public void mutateDoesNotCreateNewSession() throws Exception {
|
||||
public void mutateDoesNotCreateNewSession() {
|
||||
|
||||
WebTestClient client = WebTestClient
|
||||
.bindToWebHandler(exchange -> {
|
||||
@@ -51,8 +53,7 @@ public class MockServerTests {
|
||||
return exchange.getSession()
|
||||
.map(session -> session.getAttributeOrDefault("foo", "none"))
|
||||
.flatMap(value -> {
|
||||
byte[] bytes = value.getBytes(UTF_8);
|
||||
DataBuffer buffer = new DefaultDataBufferFactory().wrap(bytes);
|
||||
DataBuffer buffer = toDataBuffer(value);
|
||||
return exchange.getResponse().writeWith(Mono.just(buffer));
|
||||
});
|
||||
}
|
||||
@@ -74,7 +75,7 @@ public class MockServerTests {
|
||||
}
|
||||
|
||||
@Test // SPR-16059
|
||||
public void mutateDoesCopy() throws Exception {
|
||||
public void mutateDoesCopy() {
|
||||
|
||||
WebTestClient.Builder builder = WebTestClient
|
||||
.bindToWebHandler(exchange -> exchange.getResponse().setComplete())
|
||||
@@ -111,7 +112,7 @@ public class MockServerTests {
|
||||
}
|
||||
|
||||
@Test // SPR-16124
|
||||
public void exchangeResultHasCookieHeaders() throws Exception {
|
||||
public void exchangeResultHasCookieHeaders() {
|
||||
|
||||
ExchangeResult result = WebTestClient
|
||||
.bindToWebHandler(exchange -> {
|
||||
@@ -136,4 +137,32 @@ public class MockServerTests {
|
||||
result.getRequestHeaders().get(HttpHeaders.COOKIE));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void responseBodyContentWithFluxExchangeResult() {
|
||||
|
||||
FluxExchangeResult<String> result = WebTestClient
|
||||
.bindToWebHandler(exchange -> {
|
||||
ServerHttpResponse response = exchange.getResponse();
|
||||
response.getHeaders().setContentType(MediaType.TEXT_PLAIN);
|
||||
return response.writeWith(Flux.just(toDataBuffer("body")));
|
||||
})
|
||||
.build()
|
||||
.get().uri("/")
|
||||
.exchange()
|
||||
.expectStatus().isOk()
|
||||
.returnResult(String.class);
|
||||
|
||||
// Get the raw content without consuming the response body flux..
|
||||
byte[] bytes = result.getResponseBodyContent();
|
||||
|
||||
assertNotNull(bytes);
|
||||
assertEquals("body", new String(bytes, UTF_8));
|
||||
}
|
||||
|
||||
|
||||
private DataBuffer toDataBuffer(String value) {
|
||||
byte[] bytes = value.getBytes(UTF_8);
|
||||
return new DefaultDataBufferFactory().wrap(bytes);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
package org.springframework.test.web.reactive.server;
|
||||
|
||||
import java.net.URI;
|
||||
import java.time.Duration;
|
||||
|
||||
import org.junit.Test;
|
||||
import reactor.core.publisher.MonoProcessor;
|
||||
@@ -182,7 +183,7 @@ public class StatusAssertionTests {
|
||||
MonoProcessor<byte[]> emptyContent = MonoProcessor.create();
|
||||
emptyContent.onComplete();
|
||||
|
||||
ExchangeResult result = new ExchangeResult(request, response, emptyContent, emptyContent, null);
|
||||
ExchangeResult result = new ExchangeResult(request, response, emptyContent, emptyContent, Duration.ZERO, null);
|
||||
return new StatusAssertions(result, mock(WebTestClient.ResponseSpec.class));
|
||||
}
|
||||
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
package org.springframework.test.web.reactive.server;
|
||||
|
||||
import java.net.URI;
|
||||
import java.time.Duration;
|
||||
|
||||
import org.junit.Test;
|
||||
import reactor.core.publisher.Mono;
|
||||
@@ -57,7 +58,7 @@ public class WiretapConnectorTests {
|
||||
function.exchange(clientRequest).block(ofMillis(0));
|
||||
|
||||
WiretapConnector.Info actual = wiretapConnector.claimRequest("1");
|
||||
ExchangeResult result = actual.createExchangeResult(null);
|
||||
ExchangeResult result = actual.createExchangeResult(Duration.ZERO, null);
|
||||
assertEquals(HttpMethod.GET, result.getMethod());
|
||||
assertEquals("/test", result.getUrl().toString());
|
||||
}
|
||||
|
||||
@@ -16,13 +16,21 @@
|
||||
|
||||
package org.springframework.test.web.reactive.server.samples;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.test.web.reactive.server.EntityExchangeResult;
|
||||
import org.springframework.test.web.reactive.server.WebTestClient;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
/**
|
||||
* Tests with error status codes or error conditions.
|
||||
*
|
||||
@@ -35,7 +43,7 @@ public class ErrorTests {
|
||||
|
||||
|
||||
@Test
|
||||
public void notFound() throws Exception {
|
||||
public void notFound(){
|
||||
this.client.get().uri("/invalid")
|
||||
.exchange()
|
||||
.expectStatus().isNotFound()
|
||||
@@ -43,13 +51,28 @@ public class ErrorTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void serverException() throws Exception {
|
||||
public void serverException() {
|
||||
this.client.get().uri("/server-error")
|
||||
.exchange()
|
||||
.expectStatus().isEqualTo(HttpStatus.INTERNAL_SERVER_ERROR)
|
||||
.expectBody(Void.class);
|
||||
}
|
||||
|
||||
@Test // SPR-17363
|
||||
public void badRequestBeforeRequestBodyConsumed() {
|
||||
EntityExchangeResult<Void> result = this.client.post()
|
||||
.uri("/post")
|
||||
.contentType(MediaType.APPLICATION_JSON_UTF8)
|
||||
.syncBody(new Person("Dan"))
|
||||
.exchange()
|
||||
.expectStatus().isBadRequest()
|
||||
.expectBody().isEmpty();
|
||||
|
||||
byte[] content = result.getRequestBodyContent();
|
||||
assertNotNull(content);
|
||||
assertEquals("{\"name\":\"Dan\"}", new String(content, StandardCharsets.UTF_8));
|
||||
}
|
||||
|
||||
|
||||
@RestController
|
||||
static class TestController {
|
||||
@@ -58,6 +81,10 @@ public class ErrorTests {
|
||||
void handleAndThrowException() {
|
||||
throw new IllegalStateException("server error");
|
||||
}
|
||||
|
||||
@PostMapping(path = "/post", params = "p")
|
||||
void handlePost(@RequestBody Person person) {
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user