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 b1c6ba60d8..01085fae75 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 @@ -61,7 +61,7 @@ class DefaultWebTestClient implements WebTestClient { private final WebClient webClient; - private final WebTestClientConnector webTestClientConnector; + private final WiretapConnector wiretapConnector; private final Duration timeout; @@ -71,15 +71,15 @@ class DefaultWebTestClient implements WebTestClient { DefaultWebTestClient(WebClient.Builder webClientBuilder, ClientHttpConnector connector, Duration timeout) { Assert.notNull(webClientBuilder, "WebClient.Builder is required"); - this.webTestClientConnector = new WebTestClientConnector(connector); - this.webClient = webClientBuilder.clientConnector(this.webTestClientConnector).build(); + this.wiretapConnector = new WiretapConnector(connector); + this.webClient = webClientBuilder.clientConnector(this.wiretapConnector).build(); this.timeout = (timeout != null ? timeout : Duration.ofSeconds(5)); } private DefaultWebTestClient(DefaultWebTestClient webTestClient, ExchangeFilterFunction filter) { this.webClient = webTestClient.webClient.filter(filter); this.timeout = webTestClient.timeout; - this.webTestClientConnector = webTestClient.webTestClientConnector; + this.wiretapConnector = webTestClient.wiretapConnector; } @@ -174,7 +174,7 @@ class DefaultWebTestClient implements WebTestClient { DefaultHeaderSpec(WebClient.HeaderSpec spec) { this.headerSpec = spec; this.requestId = String.valueOf(requestIndex.incrementAndGet()); - this.headerSpec.header(WebTestClientConnector.REQUEST_ID_HEADER_NAME, this.requestId); + this.headerSpec.header(WiretapConnector.REQUEST_ID_HEADER_NAME, this.requestId); } @@ -254,9 +254,9 @@ class DefaultWebTestClient implements WebTestClient { } private DefaultResponseSpec toResponseSpec(Mono mono) { - ClientResponse response = mono.block(getTimeout()); - ClientHttpRequest httpRequest = webTestClientConnector.claimRequest(this.requestId); - return new DefaultResponseSpec(httpRequest, response); + ClientResponse clientResponse = mono.block(getTimeout()); + ExchangeResult exchangeResult = wiretapConnector.claimRequest(this.requestId); + return new DefaultResponseSpec(exchangeResult, clientResponse); } } @@ -268,8 +268,8 @@ class DefaultWebTestClient implements WebTestClient { private final ClientResponse response; - public UndecodedExchangeResult(ClientHttpRequest httpRequest, ClientResponse response) { - super(httpRequest, response); + public UndecodedExchangeResult(ExchangeResult result, ClientResponse response) { + super(result); this.response = response; } @@ -290,7 +290,7 @@ class DefaultWebTestClient implements WebTestClient { public FluxExchangeResult decodeBody(ResolvableType elementType) { Flux body = this.response.body(toFlux(elementType)); - return new FluxExchangeResult<>(this, body, elementType); + return new FluxExchangeResult<>(this, body); } @SuppressWarnings("unchecked") @@ -313,8 +313,8 @@ class DefaultWebTestClient implements WebTestClient { private final UndecodedExchangeResult result; - public DefaultResponseSpec(ClientHttpRequest httpRequest, ClientResponse response) { - this.result = new UndecodedExchangeResult(httpRequest, response); + public DefaultResponseSpec(ExchangeResult result, ClientResponse response) { + this.result = new UndecodedExchangeResult(result, response); } @Override 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 index 94c67d5e13..c0becbe21c 100644 --- 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 @@ -43,9 +43,4 @@ public class EntityExchangeResult extends ExchangeResult { 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 a9d0275932..3efb40c275 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 @@ -16,71 +16,66 @@ package org.springframework.test.web.reactive.server; import java.net.URI; +import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; +import java.util.Arrays; +import java.util.List; import java.util.function.Supplier; import java.util.stream.Collectors; +import reactor.core.publisher.MonoProcessor; + import org.springframework.http.HttpHeaders; import org.springframework.http.HttpMethod; import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; import org.springframework.http.ResponseCookie; -import org.springframework.http.client.reactive.ClientHttpRequest; import org.springframework.util.MultiValueMap; -import org.springframework.web.reactive.function.client.ClientResponse; /** * Simple container for request and response details from an exchange performed * through the {@link WebTestClient}. * - *

An {@code ExchangeResult} only exposes the status and the headers from - * the response which is all that's available when a {@link ClientResponse} is - * first created. + *

When an {@code ExchangeResult} is first created it has only the status and + * headers of the response available. When the response body is extracted, the + * {@code ExchangeResult} is re-created as either {@link EntityExchangeResult} + * or {@link FluxExchangeResult} that further expose extracted entities. * - *

Sub-types {@link EntityExchangeResult} and {@link FluxExchangeResult} - * further expose the response body either as a fully extracted representation - * or as a {@code Flux} of representations to be consumed. + *

Raw request and response content may also be accessed once complete via + * {@link #getRequestContent()} or {@link #getResponseContent()}. * * @author Rossen Stoyanchev * @since 5.0 + * * @see EntityExchangeResult * @see FluxExchangeResult */ public class ExchangeResult { - private final HttpMethod method; + private static final List PRINTABLE_MEDIA_TYPES = Arrays.asList( + MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML, MediaType.parseMediaType("text/*"), + MediaType.APPLICATION_FORM_URLENCODED); - private final URI url; - private final HttpHeaders requestHeaders; + private final WiretapClientHttpRequest request; - private final HttpStatus status; - - private final HttpHeaders responseHeaders; - - private final MultiValueMap responseCookies; + private final WiretapClientHttpResponse response; /** - * Constructor used when a {@code ClientResponse} is first created. + * Constructor used when the {@code ClientHttpResponse} becomes available. */ - protected 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(); - this.responseCookies = response.cookies(); + protected ExchangeResult(WiretapClientHttpRequest request, WiretapClientHttpResponse response) { + this.request = request; + this.response = response; } /** * Copy constructor used when the body is decoded or consumed. */ protected ExchangeResult(ExchangeResult other) { - this.method = other.getMethod(); - this.url = other.getUrl(); - this.requestHeaders = other.getRequestHeaders(); - this.status = other.getStatus(); - this.responseHeaders = other.getResponseHeaders(); - this.responseCookies = other.getResponseCookies(); + this.request = other.request; + this.response = other.response; } @@ -88,42 +83,56 @@ public class ExchangeResult { * Return the method of the request. */ public HttpMethod getMethod() { - return this.method; + return this.request.getMethod(); } /** * Return the request headers that were sent to the server. */ public URI getUrl() { - return this.url; + return this.request.getURI(); } /** * Return the request headers sent to the server. */ public HttpHeaders getRequestHeaders() { - return this.requestHeaders; + return this.request.getHeaders(); + } + + /** + * Return a "promise" for the raw request body content once completed. + */ + public MonoProcessor getRequestContent() { + return this.request.getBodyContent(); } /** * Return the status of the executed request. */ public HttpStatus getStatus() { - return this.status; + return this.response.getStatusCode(); } /** * Return the response headers received from the server. */ public HttpHeaders getResponseHeaders() { - return this.responseHeaders; + return this.response.getHeaders(); } /** * Return response cookies received from the server. */ public MultiValueMap getResponseCookies() { - return this.responseCookies; + return this.getResponseCookies(); + } + + /** + * Return a "promise" for the raw response body content once completed. + */ + public MonoProcessor getResponseContent() { + return this.response.getBodyContent(); } @@ -156,39 +165,60 @@ public class ExchangeResult { @Override public String toString() { - return "\n\n" + - formatValue("Request", this.method + " " + getUrl()) + - formatValue("Status", this.status + " " + getStatusReason()) + - formatHeading("Response Headers") + formatHeaders(this.responseHeaders) + - formatHeading("Request Headers") + formatHeaders(this.requestHeaders) + + return "\n" + + "> " + getMethod() + " " + getUrl() + "\n" + + "> " + formatHeaders(getRequestHeaders()) + "\n" + "\n" + - formatValue("Response Body", formatResponseBody()); + formatContent(getRequestHeaders().getContentType(), getRequestContent()) + "\n" + + "\n" + + "> " + getStatus() + " " + getStatusReason() + "\n" + + "> " + formatHeaders(getResponseHeaders()) + "\n" + + "\n" + + formatContent(getResponseHeaders().getContentType(), getResponseContent()) + "\n\n"; } private String getStatusReason() { String reason = ""; - if (this.status != null && this.status.getReasonPhrase() != null) { - reason = this.status.getReasonPhrase(); + if (getStatus() != null && getStatus().getReasonPhrase() != null) { + reason = getStatus().getReasonPhrase(); } return reason; } - private String formatHeading(String heading) { - return "\n" + String.format("%s", heading) + "\n"; - } - - private String formatValue(String label, Object value) { - return String.format("%18s: %s", label, value) + "\n"; - } - private String formatHeaders(HttpHeaders headers) { return headers.entrySet().stream() - .map(entry -> formatValue(entry.getKey(), entry.getValue())) - .collect(Collectors.joining()); + .map(entry -> entry.getKey() + ": " + entry.getValue()) + .collect(Collectors.joining("\n> ")); } - protected String formatResponseBody() { - return "Not read yet"; + private String formatContent(MediaType contentType, MonoProcessor body) { + if (body.isSuccess()) { + byte[] bytes = body.blockMillis(0); + if (bytes.length == 0) { + return "No content"; + } + + if (contentType == null) { + return "Unknown content type (" + bytes.length + " bytes)"; + } + + Charset charset = contentType.getCharset(); + if (charset != null) { + return new String(bytes, charset); + } + + if (PRINTABLE_MEDIA_TYPES.stream().anyMatch(contentType::isCompatibleWith)) { + return new String(bytes, StandardCharsets.UTF_8); + } + + return "Unknown charset (" + bytes.length + " bytes)"; + } + else if (body.isError()) { + return "I/O failure: " + body.getError().getMessage(); + } + else { + return "Content not available 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 index 76676062b1..c44371a547 100644 --- 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 @@ -17,8 +17,6 @@ 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}. * @@ -32,13 +30,10 @@ public class FluxExchangeResult extends ExchangeResult { private final Flux body; - private final ResolvableType elementType; - - FluxExchangeResult(ExchangeResult result, Flux body, ResolvableType elementType) { + FluxExchangeResult(ExchangeResult result, Flux body) { super(result); this.body = body; - this.elementType = elementType; } @@ -49,9 +44,4 @@ public class FluxExchangeResult extends ExchangeResult { 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/WiretapClientHttpRequest.java b/spring-test/src/main/java/org/springframework/test/web/reactive/server/WiretapClientHttpRequest.java new file mode 100644 index 0000000000..9924848ac6 --- /dev/null +++ b/spring-test/src/main/java/org/springframework/test/web/reactive/server/WiretapClientHttpRequest.java @@ -0,0 +1,103 @@ +/* + * 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 org.reactivestreams.Publisher; +import reactor.core.publisher.Flux; +import reactor.core.publisher.Mono; +import reactor.core.publisher.MonoProcessor; + +import org.springframework.core.io.buffer.DataBuffer; +import org.springframework.core.io.buffer.DataBufferFactory; +import org.springframework.core.io.buffer.DefaultDataBufferFactory; +import org.springframework.http.client.reactive.ClientHttpRequest; +import org.springframework.http.client.reactive.ClientHttpRequestDecorator; + +/** + * Client HTTP request decorator that saves the content written to the server. + * + * @author Rossen Stoyanchev + * @since 5.0 + */ +class WiretapClientHttpRequest extends ClientHttpRequestDecorator { + + private static final DataBufferFactory bufferFactory = new DefaultDataBufferFactory(); + + + private final DataBuffer buffer; + + private final MonoProcessor body = MonoProcessor.create(); + + + public WiretapClientHttpRequest(ClientHttpRequest delegate) { + super(delegate); + this.buffer = bufferFactory.allocateBuffer(); + } + + + /** + * Return a "promise" for the request body content. + */ + public MonoProcessor getBodyContent() { + return this.body; + } + + + @Override + public Mono writeWith(Publisher publisher) { + return super.writeWith( + Flux.from(publisher) + .doOnNext(this::handleBuffer) + .doOnError(this::handleErrorSignal) + .doOnCancel(this::handleCompleteSignal) + .doOnComplete(this::handleCompleteSignal)); + } + + @Override + public Mono writeAndFlushWith(Publisher> publisher) { + return super.writeAndFlushWith( + Flux.from(publisher) + .map(p -> Flux.from(p).doOnNext(this::handleBuffer).doOnError(this::handleErrorSignal)) + .doOnError(this::handleErrorSignal) + .doOnCancel(this::handleCompleteSignal) + .doOnComplete(this::handleCompleteSignal)); + } + + @Override + public Mono setComplete() { + handleCompleteSignal(); + return super.setComplete(); + } + + private void handleBuffer(DataBuffer buffer) { + this.buffer.write(buffer); + } + + private void handleErrorSignal(Throwable ex) { + if (!this.body.isTerminated()) { + this.body.onError(ex); + } + } + + private void handleCompleteSignal() { + if (!this.body.isTerminated()) { + byte[] bytes = new byte[this.buffer.readableByteCount()]; + this.buffer.read(bytes); + this.body.onNext(bytes); + } + } + +} diff --git a/spring-test/src/main/java/org/springframework/test/web/reactive/server/WiretapClientHttpResponse.java b/spring-test/src/main/java/org/springframework/test/web/reactive/server/WiretapClientHttpResponse.java new file mode 100644 index 0000000000..c4fd81575f --- /dev/null +++ b/spring-test/src/main/java/org/springframework/test/web/reactive/server/WiretapClientHttpResponse.java @@ -0,0 +1,73 @@ +/* + * 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 reactor.core.publisher.MonoProcessor; + +import org.springframework.core.io.buffer.DataBuffer; +import org.springframework.core.io.buffer.DataBufferFactory; +import org.springframework.core.io.buffer.DefaultDataBufferFactory; +import org.springframework.http.client.reactive.ClientHttpResponse; +import org.springframework.http.client.reactive.ClientHttpResponseDecorator; + +/** + * Client HTTP response decorator that saves the content read from the server. + * + * @author Rossen Stoyanchev + * @since 5.0 + */ +class WiretapClientHttpResponse extends ClientHttpResponseDecorator { + + private static final DataBufferFactory bufferFactory = new DefaultDataBufferFactory(); + + + private final DataBuffer buffer; + + private final MonoProcessor body = MonoProcessor.create(); + + + public WiretapClientHttpResponse(ClientHttpResponse delegate) { + super(delegate); + this.buffer = bufferFactory.allocateBuffer(); + } + + + /** + * Return a "promise" for the response body content. + */ + public MonoProcessor getBodyContent() { + return this.body; + } + + @Override + public Flux getBody() { + return super.getBody() + .doOnNext(buffer::write) + .doOnError(body::onError) + .doOnCancel(this::handleCompleteSignal) + .doOnComplete(this::handleCompleteSignal); + } + + private void handleCompleteSignal() { + if (!this.body.isTerminated()) { + byte[] bytes = new byte[this.buffer.readableByteCount()]; + this.buffer.read(bytes); + this.body.onNext(bytes); + } + } + +} diff --git a/spring-test/src/main/java/org/springframework/test/web/reactive/server/WebTestClientConnector.java b/spring-test/src/main/java/org/springframework/test/web/reactive/server/WiretapConnector.java similarity index 59% rename from spring-test/src/main/java/org/springframework/test/web/reactive/server/WebTestClientConnector.java rename to spring-test/src/main/java/org/springframework/test/web/reactive/server/WiretapConnector.java index be638f8047..84f2cdf434 100644 --- a/spring-test/src/main/java/org/springframework/test/web/reactive/server/WebTestClientConnector.java +++ b/spring-test/src/main/java/org/springframework/test/web/reactive/server/WiretapConnector.java @@ -31,24 +31,24 @@ import org.springframework.util.Assert; /** * Decorate any other {@link ClientHttpConnector} with the purpose of - * intercepting, capturing, and exposing {@code ClientHttpRequest}s reflecting - * the exact and complete details sent to the server. + * intercepting, capturing, and exposing actual request and response content + * transmitted to and received from the server. * * @author Rossen Stoyanchev * @since 5.0 * @see HttpHandlerConnector */ -class WebTestClientConnector implements ClientHttpConnector { +class WiretapConnector implements ClientHttpConnector { public static final String REQUEST_ID_HEADER_NAME = "request-id"; private final ClientHttpConnector delegate; - private final Map capturedRequests = new ConcurrentHashMap<>(); + private final Map capturedExchanges = new ConcurrentHashMap<>(); - public WebTestClientConnector(ClientHttpConnector delegate) { + public WiretapConnector(ClientHttpConnector delegate) { this.delegate = delegate; } @@ -57,29 +57,32 @@ class WebTestClientConnector implements ClientHttpConnector { public Mono connect(HttpMethod method, URI uri, Function> requestCallback) { - AtomicReference requestRef = new AtomicReference<>(); + AtomicReference requestRef = new AtomicReference<>(); return this.delegate .connect(method, uri, request -> { - requestRef.set(request); - return requestCallback.apply(request); + WiretapClientHttpRequest wrapped = new WiretapClientHttpRequest(request); + requestRef.set(wrapped); + return requestCallback.apply(wrapped); }) - .doOnNext(response -> { - ClientHttpRequest request = requestRef.get(); - String id = request.getHeaders().getFirst(REQUEST_ID_HEADER_NAME); - if (id != null) { - this.capturedRequests.put(id, request); - } + .map(response -> { + WiretapClientHttpRequest request = requestRef.get(); + String requestId = request.getHeaders().getFirst(REQUEST_ID_HEADER_NAME); + Assert.notNull(requestId, "No request-id header"); + WiretapClientHttpResponse wrapped = new WiretapClientHttpResponse(response); + ExchangeResult result = new ExchangeResult(request, wrapped); + this.capturedExchanges.put(requestId, result); + return wrapped; }); } /** * Retrieve the request with the given "request-id" header. */ - public ClientHttpRequest claimRequest(String requestId) { - ClientHttpRequest request = this.capturedRequests.get(requestId); - Assert.notNull(request, "No matching request [" + requestId + "]. Did connect return a response yet?"); - return request; + public ExchangeResult claimRequest(String requestId) { + ExchangeResult result = this.capturedExchanges.get(requestId); + Assert.notNull(result, "No match for request with id [" + requestId + "]"); + return result; } } diff --git a/spring-test/src/test/java/org/springframework/test/web/reactive/server/HeaderAssertionsTests.java b/spring-test/src/test/java/org/springframework/test/web/reactive/server/HeaderAssertionsTests.java index 70e9382ce2..7e16e29a3a 100644 --- a/spring-test/src/test/java/org/springframework/test/web/reactive/server/HeaderAssertionsTests.java +++ b/spring-test/src/test/java/org/springframework/test/web/reactive/server/HeaderAssertionsTests.java @@ -23,8 +23,10 @@ import org.junit.Test; import org.springframework.http.CacheControl; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpMethod; +import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; import org.springframework.mock.http.client.reactive.MockClientHttpRequest; +import org.springframework.mock.http.client.reactive.MockClientHttpResponse; import org.springframework.web.reactive.function.client.ClientResponse; import static junit.framework.TestCase.assertNotNull; @@ -146,15 +148,14 @@ public class HeaderAssertionsTests { private HeaderAssertions headerAssertions(HttpHeaders responseHeaders) { - ClientResponse.Headers headers = mock(ClientResponse.Headers.class); - when(headers.asHttpHeaders()).thenReturn(responseHeaders); - - ClientResponse response = mock(ClientResponse.class); - when(response.headers()).thenReturn(headers); - MockClientHttpRequest request = new MockClientHttpRequest(HttpMethod.GET, URI.create("/")); - ExchangeResult result = new ExchangeResult(request, response); + MockClientHttpResponse response = new MockClientHttpResponse(HttpStatus.OK); + response.getHeaders().putAll(responseHeaders); + WiretapClientHttpRequest wiretapRequest = new WiretapClientHttpRequest(request); + WiretapClientHttpResponse wiretapResponse = new WiretapClientHttpResponse(response); + + ExchangeResult result = new ExchangeResult(wiretapRequest, wiretapResponse); return new HeaderAssertions(result, mock(WebTestClient.ResponseSpec.class)); } diff --git a/spring-test/src/test/java/org/springframework/test/web/reactive/server/StatusAssertionTests.java b/spring-test/src/test/java/org/springframework/test/web/reactive/server/StatusAssertionTests.java index beabc3a7b8..6da97daba2 100644 --- a/spring-test/src/test/java/org/springframework/test/web/reactive/server/StatusAssertionTests.java +++ b/spring-test/src/test/java/org/springframework/test/web/reactive/server/StatusAssertionTests.java @@ -23,6 +23,7 @@ import org.springframework.http.HttpHeaders; import org.springframework.http.HttpMethod; import org.springframework.http.HttpStatus; import org.springframework.mock.http.client.reactive.MockClientHttpRequest; +import org.springframework.mock.http.client.reactive.MockClientHttpResponse; import org.springframework.web.reactive.function.client.ClientResponse; import static org.junit.Assert.fail; @@ -162,17 +163,14 @@ public class StatusAssertionTests { private StatusAssertions statusAssertions(HttpStatus status) { - ClientResponse.Headers headers = mock(ClientResponse.Headers.class); - when(headers.asHttpHeaders()).thenReturn(new HttpHeaders()); - - ClientResponse response = mock(ClientResponse.class); - when(response.statusCode()).thenReturn(status); - when(response.headers()).thenReturn(headers); - MockClientHttpRequest request = new MockClientHttpRequest(HttpMethod.GET, URI.create("/")); - ExchangeResult result = new ExchangeResult(request, response); + MockClientHttpResponse response = new MockClientHttpResponse(status); - return new StatusAssertions(result, mock(WebTestClient.ResponseSpec.class)); + WiretapClientHttpRequest wiretapRequest = new WiretapClientHttpRequest(request); + WiretapClientHttpResponse wiretapResponse = new WiretapClientHttpResponse(response); + + ExchangeResult exchangeResult = new ExchangeResult(wiretapRequest, wiretapResponse); + return new StatusAssertions(exchangeResult, mock(WebTestClient.ResponseSpec.class)); } } diff --git a/spring-test/src/test/java/org/springframework/test/web/reactive/server/WebTestClientConnectorTests.java b/spring-test/src/test/java/org/springframework/test/web/reactive/server/WebTestClientConnectorTests.java index 2c12059de1..608ddb96d7 100644 --- a/spring-test/src/test/java/org/springframework/test/web/reactive/server/WebTestClientConnectorTests.java +++ b/spring-test/src/test/java/org/springframework/test/web/reactive/server/WebTestClientConnectorTests.java @@ -36,7 +36,7 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; /** - * Unit tests for {@link WebTestClientConnector}. + * Unit tests for {@link WiretapConnector}. * * @author Rossen Stoyanchev */ @@ -50,16 +50,16 @@ public class WebTestClientConnectorTests { ClientHttpConnector connector = (method, uri, fn) -> fn.apply(request).then(Mono.just(response)); ClientRequest clientRequest = ClientRequest.method(HttpMethod.GET, URI.create("/test")) - .header(WebTestClientConnector.REQUEST_ID_HEADER_NAME, "1").build(); + .header(WiretapConnector.REQUEST_ID_HEADER_NAME, "1").build(); - WebTestClientConnector webTestClientConnector = new WebTestClientConnector(connector); - ExchangeFunction function = ExchangeFunctions.create(webTestClientConnector); + WiretapConnector wiretapConnector = new WiretapConnector(connector); + ExchangeFunction function = ExchangeFunctions.create(wiretapConnector); function.exchange(clientRequest).blockMillis(0); - ClientHttpRequest actual = webTestClientConnector.claimRequest("1"); + ExchangeResult actual = wiretapConnector.claimRequest("1"); assertNotNull(actual); assertEquals(HttpMethod.GET, actual.getMethod()); - assertEquals("/test", actual.getURI().toString()); + assertEquals("/test", actual.getUrl().toString()); } }