Browse Source

Upgrade tests to OkHttp 5.x

See https://square.github.io/okhttp/changelogs/changelog/#version-500.

Closes gh-35183
pull/35212/head
Sébastien Deleuze 8 months ago
parent
commit
19086835a7
  1. 2
      framework-platform/framework-platform.gradle
  2. 2
      spring-core/spring-core.gradle
  3. 38
      spring-core/src/test/java/org/springframework/core/io/ResourceTests.java
  4. 2
      spring-web/spring-web.gradle
  5. 77
      spring-web/src/test/java/org/springframework/http/client/AbstractMockWebServerTests.java
  6. 56
      spring-web/src/test/java/org/springframework/http/client/reactive/ClientHttpConnectorTests.java
  7. 157
      spring-web/src/test/java/org/springframework/web/client/AbstractMockWebServerTests.java
  8. 412
      spring-web/src/test/java/org/springframework/web/client/RestClientIntegrationTests.java
  9. 36
      spring-web/src/test/java/org/springframework/web/client/RestClientVersionTests.java
  10. 20
      spring-web/src/test/java/org/springframework/web/client/RestTemplateTests.java
  11. 98
      spring-web/src/test/java/org/springframework/web/client/support/RestClientAdapterTests.java
  12. 22
      spring-web/src/test/java/org/springframework/web/client/support/RestClientProxyRegistryIntegrationTests.java
  13. 48
      spring-web/src/test/kotlin/org/springframework/web/client/support/KotlinRestTemplateHttpServiceProxyTests.kt
  14. 2
      spring-webflux/spring-webflux.gradle
  15. 61
      spring-webflux/src/test/java/org/springframework/web/reactive/function/client/WebClientDataBufferAllocatingTests.java
  16. 433
      spring-webflux/src/test/java/org/springframework/web/reactive/function/client/WebClientIntegrationTests.java
  17. 33
      spring-webflux/src/test/java/org/springframework/web/reactive/function/client/WebClientVersionTests.java
  18. 68
      spring-webflux/src/test/java/org/springframework/web/reactive/function/client/support/WebClientAdapterTests.java
  19. 22
      spring-webflux/src/test/java/org/springframework/web/reactive/function/client/support/WebClientProxyRegistryIntegrationTests.java
  20. 67
      spring-webflux/src/test/kotlin/org/springframework/web/reactive/function/client/support/WebClientHttpServiceProxyKotlinTests.kt

2
framework-platform/framework-platform.gradle

@ -37,7 +37,7 @@ dependencies { @@ -37,7 +37,7 @@ dependencies {
api("com.networknt:json-schema-validator:1.5.3")
api("com.oracle.database.jdbc:ojdbc11:21.9.0.0")
api("com.rometools:rome:1.19.0")
api("com.squareup.okhttp3:mockwebserver:3.14.9")
api("com.squareup.okhttp3:mockwebserver3:5.1.0")
api("com.sun.activation:jakarta.activation:2.0.1")
api("com.sun.xml.bind:jaxb-core:3.0.2")
api("com.sun.xml.bind:jaxb-impl:3.0.2")

2
spring-core/spring-core.gradle

@ -96,7 +96,7 @@ dependencies { @@ -96,7 +96,7 @@ dependencies {
testImplementation("com.fasterxml.jackson.core:jackson-databind")
testImplementation("com.fasterxml.woodstox:woodstox-core")
testImplementation("com.google.code.findbugs:jsr305")
testImplementation("com.squareup.okhttp3:mockwebserver")
testImplementation("com.squareup.okhttp3:mockwebserver3")
testImplementation("io.projectreactor:reactor-test")
testImplementation("io.projectreactor.tools:blockhound")
testImplementation("jakarta.annotation:jakarta.annotation-api")

38
spring-core/src/test/java/org/springframework/core/io/ResourceTests.java

@ -37,10 +37,10 @@ import java.util.Base64; @@ -37,10 +37,10 @@ import java.util.Base64;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.stream.Stream;
import okhttp3.mockwebserver.Dispatcher;
import okhttp3.mockwebserver.MockResponse;
import okhttp3.mockwebserver.MockWebServer;
import okhttp3.mockwebserver.RecordedRequest;
import mockwebserver3.Dispatcher;
import mockwebserver3.MockResponse;
import mockwebserver3.MockWebServer;
import mockwebserver3.RecordedRequest;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;
@ -419,7 +419,7 @@ class ResourceTests { @@ -419,7 +419,7 @@ class ResourceTests {
assertThat(resource.exists()).isTrue();
RecordedRequest request = this.server.takeRequest();
assertThat(request.getMethod()).isEqualTo("HEAD");
assertThat(request.getHeader("Framework-Name")).isEqualTo("Spring");
assertThat(request.getHeaders().get("Framework-Name")).isEqualTo("Spring");
}
@Test
@ -429,7 +429,7 @@ class ResourceTests { @@ -429,7 +429,7 @@ class ResourceTests {
assertThat(resource.exists()).isTrue();
RecordedRequest request = this.server.takeRequest();
assertThat(request.getMethod()).isEqualTo("HEAD");
assertThat(request.getHeader("Framework-Name")).isEqualTo("Spring");
assertThat(request.getHeaders().get("Framework-Name")).isEqualTo("Spring");
}
@Test
@ -439,7 +439,7 @@ class ResourceTests { @@ -439,7 +439,7 @@ class ResourceTests {
assertThat(resource.getInputStream()).hasContent("Spring");
RecordedRequest request = this.server.takeRequest();
assertThat(request.getMethod()).isEqualTo("GET");
assertThat(request.getHeader("Framework-Name")).isEqualTo("Spring");
assertThat(request.getHeaders().get("Framework-Name")).isEqualTo("Spring");
}
@Test
@ -449,15 +449,15 @@ class ResourceTests { @@ -449,15 +449,15 @@ class ResourceTests {
"http://alice:secret@localhost:" + this.server.getPort() + "/resource");
assertThat(resource.getInputStream()).hasContent("Spring");
RecordedRequest request = this.server.takeRequest();
String authorization = request.getHeader("Authorization");
String authorization = request.getHeaders().get("Authorization");
assertThat(authorization).isNotNull().startsWith("Basic ");
assertThat(new String(Base64.getDecoder().decode(authorization.substring(6)),
StandardCharsets.ISO_8859_1)).isEqualTo("alice:secret");
}
@AfterEach
void shutdown() throws Exception {
this.server.shutdown();
void shutdown() {
this.server.close();
}
private String startServer(boolean withHeadSupport) throws Exception {
@ -488,23 +488,25 @@ class ResourceTests { @@ -488,23 +488,25 @@ class ResourceTests {
@Override
public MockResponse dispatch(RecordedRequest request) {
if (request.getPath().equals("/resource")) {
if (request.getTarget().equals("/resource")) {
return switch (request.getMethod()) {
case "HEAD" -> (this.withHeadSupport ?
new MockResponse()
new MockResponse.Builder()
.addHeader("Content-Type", "text/plain")
.addHeader("Content-Length", "6")
.addHeader("Last-Modified", LAST_MODIFIED) :
new MockResponse().setResponseCode(405));
case "GET" -> new MockResponse()
.addHeader("Last-Modified", LAST_MODIFIED)
.build() :
new MockResponse.Builder().code(405).build());
case "GET" -> new MockResponse.Builder()
.addHeader("Content-Type", "text/plain")
.addHeader("Content-Length", "6")
.addHeader("Last-Modified", LAST_MODIFIED)
.setBody("Spring");
default -> new MockResponse().setResponseCode(404);
.body("Spring")
.build();
default -> new MockResponse.Builder().code(404).build();
};
}
return new MockResponse().setResponseCode(404);
return new MockResponse.Builder().code(404).build();
}
}
}

2
spring-web/spring-web.gradle

@ -82,7 +82,7 @@ dependencies { @@ -82,7 +82,7 @@ dependencies {
testImplementation("com.fasterxml.jackson.module:jackson-module-kotlin")
testImplementation("com.fasterxml.jackson.module:jackson-module-parameter-names")
testImplementation("com.fasterxml.jackson.dataformat:jackson-dataformat-csv")
testImplementation("com.squareup.okhttp3:mockwebserver")
testImplementation("com.squareup.okhttp3:mockwebserver3")
testImplementation("io.micrometer:micrometer-observation-test")
testImplementation("io.projectreactor:reactor-test")
testImplementation("io.projectreactor.tools:blockhound")

77
spring-web/src/test/java/org/springframework/http/client/AbstractMockWebServerTests.java

@ -16,10 +16,10 @@ @@ -16,10 +16,10 @@
package org.springframework.http.client;
import okhttp3.mockwebserver.Dispatcher;
import okhttp3.mockwebserver.MockResponse;
import okhttp3.mockwebserver.MockWebServer;
import okhttp3.mockwebserver.RecordedRequest;
import mockwebserver3.Dispatcher;
import mockwebserver3.MockResponse;
import mockwebserver3.MockWebServer;
import mockwebserver3.RecordedRequest;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
@ -49,8 +49,8 @@ public abstract class AbstractMockWebServerTests { @@ -49,8 +49,8 @@ public abstract class AbstractMockWebServerTests {
}
@AfterEach
void tearDown() throws Exception {
this.server.shutdown();
void tearDown() {
this.server.close();
}
@ -59,56 +59,57 @@ public abstract class AbstractMockWebServerTests { @@ -59,56 +59,57 @@ public abstract class AbstractMockWebServerTests {
@Override
public MockResponse dispatch(RecordedRequest request) {
try {
if (request.getPath().equals("/echo")) {
assertThat(request.getHeader("Host")).contains("localhost:" + port);
MockResponse response = new MockResponse()
.setHeaders(request.getHeaders())
.setHeader("Content-Length", request.getBody().size())
.setResponseCode(200)
.setBody(request.getBody());
request.getBody().flush();
return response;
if (request.getTarget().equals("/echo")) {
assertThat(request.getHeaders().get("Host")).contains("localhost:" + port);
MockResponse.Builder builder = new MockResponse.Builder().headers(request.getHeaders());
if (request.getBody() != null) {
builder = builder.body(request.getBody().utf8());
}
else {
builder.setHeader("Content-Length", 0);
}
return builder.code(200).build();
}
else if(request.getPath().equals("/status/ok")) {
return new MockResponse();
else if(request.getTarget().equals("/status/ok")) {
return new MockResponse.Builder().build();
}
else if(request.getPath().equals("/status/notfound")) {
return new MockResponse().setResponseCode(404);
else if(request.getTarget().equals("/status/notfound")) {
return new MockResponse.Builder().code(404).build();
}
else if (request.getPath().equals("/status/299")) {
assertThat(request.getHeader("Expect")).contains("299");
return new MockResponse().setResponseCode(299);
else if (request.getTarget().equals("/status/299")) {
assertThat(request.getHeaders().get("Expect")).contains("299");
return new MockResponse.Builder().code(299).build();
}
else if(request.getPath().startsWith("/params")) {
assertThat(request.getPath()).contains("param1=value");
assertThat(request.getPath()).contains("param2=value1&param2=value2");
return new MockResponse();
else if(request.getTarget().startsWith("/params")) {
assertThat(request.getTarget()).contains("param1=value");
assertThat(request.getTarget()).contains("param2=value1&param2=value2");
return new MockResponse.Builder().build();
}
else if(request.getPath().equals("/methods/post")) {
else if(request.getTarget().equals("/methods/post")) {
assertThat(request.getMethod()).isEqualTo("POST");
String transferEncoding = request.getHeader("Transfer-Encoding");
String transferEncoding = request.getHeaders().get("Transfer-Encoding");
if(StringUtils.hasLength(transferEncoding)) {
assertThat(transferEncoding).isEqualTo("chunked");
}
else {
long contentLength = Long.parseLong(request.getHeader("Content-Length"));
long contentLength = Long.parseLong(request.getHeaders().get("Content-Length"));
assertThat(request.getBody().size()).isEqualTo(contentLength);
}
return new MockResponse().setResponseCode(200);
return new MockResponse.Builder().code(200).build();
}
else if(request.getPath().startsWith("/methods/")) {
String expectedMethod = request.getPath().replace("/methods/","").toUpperCase();
else if(request.getTarget().startsWith("/methods/")) {
String expectedMethod = request.getTarget().replace("/methods/","").toUpperCase();
assertThat(request.getMethod()).isEqualTo(expectedMethod);
return new MockResponse();
return new MockResponse.Builder().build();
}
else if(request.getPath().startsWith("/header/")) {
String headerName = request.getPath().replace("/header/","");
return new MockResponse().setBody(headerName + ":" + request.getHeader(headerName)).setResponseCode(200);
else if(request.getTarget().startsWith("/header/")) {
String headerName = request.getTarget().replace("/header/","");
return new MockResponse.Builder().body(headerName + ":" + request.getHeaders().get(headerName)).code(200).build();
}
return new MockResponse().setResponseCode(404);
return new MockResponse.Builder().code(404).build();
}
catch (Throwable ex) {
return new MockResponse().setResponseCode(500).setBody(ex.toString());
return new MockResponse.Builder().code(500).body(ex.toString()).build();
}
}
}

56
spring-web/src/test/java/org/springframework/http/client/reactive/ClientHttpConnectorTests.java

@ -34,10 +34,11 @@ import java.util.Random; @@ -34,10 +34,11 @@ import java.util.Random;
import java.util.Set;
import java.util.concurrent.CountDownLatch;
import java.util.function.Consumer;
import java.util.function.Function;
import okhttp3.mockwebserver.MockResponse;
import okhttp3.mockwebserver.MockWebServer;
import okhttp3.mockwebserver.RecordedRequest;
import mockwebserver3.MockResponse;
import mockwebserver3.MockWebServer;
import mockwebserver3.RecordedRequest;
import okio.Buffer;
import org.apache.hc.client5.http.impl.async.HttpAsyncClientBuilder;
import org.junit.jupiter.api.AfterEach;
@ -84,8 +85,8 @@ class ClientHttpConnectorTests { @@ -84,8 +85,8 @@ class ClientHttpConnectorTests {
}
@AfterEach
void stopServer() throws IOException {
server.shutdown();
void stopServer() {
server.close();
}
// Do not auto-close arguments since HttpComponentsClientHttpConnector implements
@ -96,11 +97,10 @@ class ClientHttpConnectorTests { @@ -96,11 +97,10 @@ class ClientHttpConnectorTests {
URI uri = this.server.url("/").uri();
String responseBody = "bar\r\n";
prepareResponse(response -> {
response.setResponseCode(200);
response.addHeader("Baz", "Qux");
response.setBody(responseBody);
});
prepareResponse(builder -> builder
.code(200)
.addHeader("Baz", "Qux")
.body(responseBody));
String requestBody = "foo\r\n";
boolean requestHasBody = METHODS_WITH_BODY.contains(method);
@ -144,9 +144,9 @@ class ClientHttpConnectorTests { @@ -144,9 +144,9 @@ class ClientHttpConnectorTests {
expectRequest(request -> {
assertThat(request.getMethod()).isEqualTo(method.name());
assertThat(request.getHeader("Foo")).isEqualTo("Bar");
assertThat(request.getHeaders().get("Foo")).isEqualTo("Bar");
if (requestHasBody) {
assertThat(request.getBody().readUtf8()).isEqualTo(requestBody);
assertThat(request.getBody().utf8()).isEqualTo(requestBody);
}
});
}
@ -158,7 +158,7 @@ class ClientHttpConnectorTests { @@ -158,7 +158,7 @@ class ClientHttpConnectorTests {
stringBuffer("foo"),
Mono.error(error)
);
prepareResponse(response -> response.setResponseCode(200));
prepareResponse(builder -> builder.code(200));
Mono<ClientHttpResponse> futureResponse =
connector.connect(HttpMethod.POST, this.server.url("/").uri(), request -> request.writeWith(body));
StepVerifier.create(futureResponse)
@ -169,7 +169,7 @@ class ClientHttpConnectorTests { @@ -169,7 +169,7 @@ class ClientHttpConnectorTests {
@ParameterizedConnectorTest
void cancelResponseBody(ClientHttpConnector connector) {
Buffer responseBody = randomBody(100);
prepareResponse(response -> response.setBody(responseBody));
prepareResponse(builder -> builder.body(responseBody));
ClientHttpResponse response = connector.connect(HttpMethod.POST, this.server.url("/").uri(),
ReactiveHttpOutputMessage::setComplete).block();
@ -187,10 +187,9 @@ class ClientHttpConnectorTests { @@ -187,10 +187,9 @@ class ClientHttpConnectorTests {
ZonedDateTime tomorrow = ZonedDateTime.now(ZoneId.of("UTC")).plusDays(1);
String formattedDate = tomorrow.format(DateTimeFormatter.RFC_1123_DATE_TIME);
prepareResponse(response -> {
response.setResponseCode(200);
response.addHeader("Set-Cookie", "id=test; Expires= " + formattedDate + ";");
});
prepareResponse(builder -> builder
.code(200)
.addHeader("Set-Cookie", "id=test; Expires= " + formattedDate + ";"));
Mono<ClientHttpResponse> futureResponse =
connector.connect(HttpMethod.GET, this.server.url("/").uri(), ReactiveHttpOutputMessage::setComplete);
StepVerifier.create(futureResponse)
@ -206,10 +205,9 @@ class ClientHttpConnectorTests { @@ -206,10 +205,9 @@ class ClientHttpConnectorTests {
void partitionedCookieSupport(ClientHttpConnector connector) {
Assumptions.assumeFalse(connector instanceof JettyClientHttpConnector, "Jetty client does not support partitioned cookies");
Assumptions.assumeFalse(connector instanceof JdkClientHttpConnector, "JDK client does not support partitioned cookies");
prepareResponse(response -> {
response.setResponseCode(200);
response.addHeader("Set-Cookie", "id=test; Partitioned;");
});
prepareResponse(builder -> builder
.code(200)
.addHeader("Set-Cookie", "id=test; Partitioned;"));
Mono<ClientHttpResponse> futureResponse =
connector.connect(HttpMethod.GET, this.server.url("/").uri(), ReactiveHttpOutputMessage::setComplete);
StepVerifier.create(futureResponse)
@ -227,10 +225,9 @@ class ClientHttpConnectorTests { @@ -227,10 +225,9 @@ class ClientHttpConnectorTests {
HttpAsyncClientBuilder.create().disableCookieManagement().build()
);
prepareResponse(response -> {
response.setResponseCode(200);
response.addHeader("Set-Cookie", "id=test;");
});
prepareResponse(builder -> builder
.code(200)
.addHeader("Set-Cookie", "id=test;"));
Mono<ClientHttpResponse> futureResponse =
connector.connect(HttpMethod.GET, this.server.url("/").uri(), ReactiveHttpOutputMessage::setComplete);
StepVerifier.create(futureResponse)
@ -254,10 +251,9 @@ class ClientHttpConnectorTests { @@ -254,10 +251,9 @@ class ClientHttpConnectorTests {
return responseBody;
}
private void prepareResponse(Consumer<MockResponse> consumer) {
MockResponse response = new MockResponse();
consumer.accept(response);
this.server.enqueue(response);
private void prepareResponse(Function<MockResponse.Builder, MockResponse.Builder> f) {
MockResponse.Builder builder = new MockResponse.Builder();
this.server.enqueue(f.apply(builder).build());
}
private void expectRequest(Consumer<RecordedRequest> consumer) {

157
spring-web/src/test/java/org/springframework/web/client/AbstractMockWebServerTests.java

@ -21,11 +21,12 @@ import java.nio.charset.Charset; @@ -21,11 +21,12 @@ import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.util.Collections;
import okhttp3.mockwebserver.Dispatcher;
import okhttp3.mockwebserver.MockResponse;
import okhttp3.mockwebserver.MockWebServer;
import okhttp3.mockwebserver.RecordedRequest;
import mockwebserver3.Dispatcher;
import mockwebserver3.MockResponse;
import mockwebserver3.MockWebServer;
import mockwebserver3.RecordedRequest;
import okio.Buffer;
import org.jspecify.annotations.Nullable;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
@ -68,96 +69,102 @@ abstract class AbstractMockWebServerTests { @@ -68,96 +69,102 @@ abstract class AbstractMockWebServerTests {
@AfterEach
void tearDown() throws Exception {
this.server.shutdown();
this.server.close();
}
private MockResponse getRequest(RecordedRequest request, byte[] body, String contentType) {
private MockResponse getRequest(RecordedRequest request, byte[] body, @Nullable String contentType) {
if (request.getMethod().equals("OPTIONS")) {
return new MockResponse().setResponseCode(200).setHeader("Allow", "GET, OPTIONS, HEAD, TRACE");
return new MockResponse.Builder().code(200).setHeader("Allow", "GET, OPTIONS, HEAD, TRACE").build();
}
Buffer buf = new Buffer();
buf.write(body);
MockResponse response = new MockResponse()
MockResponse.Builder builder = new MockResponse.Builder()
.setHeader(CONTENT_LENGTH, body.length)
.setBody(buf)
.setResponseCode(200);
.body(buf)
.code(200);
if (contentType != null) {
response = response.setHeader(CONTENT_TYPE, contentType);
return builder.setHeader(CONTENT_TYPE, contentType).build();
}
else {
return builder.build();
}
return response;
}
private MockResponse postRequest(RecordedRequest request, String expectedRequestContent,
String location, String contentType, byte[] responseBody) {
assertThat(request.getHeaders().values(CONTENT_LENGTH)).hasSize(1);
assertThat(Integer.parseInt(request.getHeader(CONTENT_LENGTH))).as("Invalid request content-length").isGreaterThan(0);
String requestContentType = request.getHeader(CONTENT_TYPE);
assertThat(Integer.parseInt(request.getHeaders().get(CONTENT_LENGTH))).as("Invalid request content-length").isGreaterThan(0);
String requestContentType = request.getHeaders().get(CONTENT_TYPE);
assertThat(requestContentType).as("No content-type").isNotNull();
Charset charset = StandardCharsets.ISO_8859_1;
if (requestContentType.contains("charset=")) {
String charsetName = requestContentType.split("charset=")[1];
charset = Charset.forName(charsetName);
}
assertThat(request.getBody().readString(charset)).as("Invalid request body").isEqualTo(expectedRequestContent);
assertThat(request.getBody().string(charset)).as("Invalid request body").isEqualTo(expectedRequestContent);
Buffer buf = new Buffer();
buf.write(responseBody);
return new MockResponse()
return new MockResponse.Builder()
.setHeader(LOCATION, baseUrl + location)
.setHeader(CONTENT_TYPE, contentType)
.setHeader(CONTENT_LENGTH, responseBody.length)
.setBody(buf)
.setResponseCode(201);
.body(buf)
.code(201)
.build();
}
private MockResponse jsonPostRequest(RecordedRequest request, String location, String contentType) {
if (request.getBodySize() > 0) {
String contentLength = request.getHeader(CONTENT_LENGTH);
String contentLength = request.getHeaders().get(CONTENT_LENGTH);
if (contentLength != null) {
assertThat(Integer.parseInt(contentLength)).as("Invalid request content-length").isGreaterThan(0);
}
assertThat(request.getHeader(CONTENT_TYPE)).as("No content-type").isNotNull();
assertThat(request.getHeaders().get(CONTENT_TYPE)).as("No content-type").isNotNull();
}
return new MockResponse()
return new MockResponse.Builder()
.setHeader(LOCATION, baseUrl + location)
.setHeader(CONTENT_TYPE, contentType)
.setHeader(CONTENT_LENGTH, request.getBody().size())
.setBody(request.getBody())
.setResponseCode(201);
.body(request.getBody().utf8())
.code(201)
.build();
}
private MockResponse multipartFormDataRequest(RecordedRequest request) {
MediaType mediaType = MediaType.parseMediaType(request.getHeader(CONTENT_TYPE));
MediaType mediaType = MediaType.parseMediaType(request.getHeaders().get(CONTENT_TYPE));
assertThat(mediaType.isCompatibleWith(MULTIPART_FORM_DATA)).as(MULTIPART_FORM_DATA.toString()).isTrue();
assertMultipart(request, mediaType);
return new MockResponse().setResponseCode(200);
return new MockResponse.Builder().code(200).build();
}
private MockResponse multipartMixedRequest(RecordedRequest request) {
MediaType mediaType = MediaType.parseMediaType(request.getHeader(CONTENT_TYPE));
MediaType mediaType = MediaType.parseMediaType(request.getHeaders().get(CONTENT_TYPE));
assertThat(mediaType.isCompatibleWith(MULTIPART_MIXED)).as(MULTIPART_MIXED.toString()).isTrue();
assertMultipart(request, mediaType);
return new MockResponse().setResponseCode(200);
return new MockResponse.Builder().code(200).build();
}
private MockResponse multipartRelatedRequest(RecordedRequest request) {
MediaType mediaType = MediaType.parseMediaType(request.getHeader(CONTENT_TYPE));
MediaType mediaType = MediaType.parseMediaType(request.getHeaders().get(CONTENT_TYPE));
assertThat(mediaType.isCompatibleWith(MULTIPART_RELATED)).as(MULTIPART_RELATED.toString()).isTrue();
assertMultipart(request, mediaType);
return new MockResponse().setResponseCode(200);
return new MockResponse.Builder().code(200).build();
}
private void assertMultipart(RecordedRequest request, MediaType mediaType) {
assertThat(mediaType.isCompatibleWith(new MediaType("multipart", "*"))).as("multipart/*").isTrue();
String boundary = mediaType.getParameter("boundary");
assertThat(boundary).as("boundary").isNotBlank();
Buffer body = request.getBody();
try {
assertPart(body, "form-data", boundary, "name 1", "text/plain", "value 1");
assertPart(body, "form-data", boundary, "name 2", "text/plain", "value 2+1");
assertPart(body, "form-data", boundary, "name 2", "text/plain", "value 2+2");
assertFilePart(body, "form-data", boundary, "logo", "logo.jpg", "image/jpeg");
try (Buffer buffer = new Buffer()) {
assertThat(request.getBody()).isNotNull();
buffer.write(request.getBody());
assertPart(buffer, "form-data", boundary, "name 1", "text/plain", "value 1");
assertPart(buffer, "form-data", boundary, "name 2", "text/plain", "value 2+1");
assertPart(buffer, "form-data", boundary, "name 2", "text/plain", "value 2+2");
assertFilePart(buffer, "form-data", boundary, "logo", "logo.jpg", "image/jpeg");
}
catch (EOFException ex) {
throw new AssertionError(ex);
@ -192,43 +199,45 @@ abstract class AbstractMockWebServerTests { @@ -192,43 +199,45 @@ abstract class AbstractMockWebServerTests {
}
private MockResponse formRequest(RecordedRequest request) {
assertThat(request.getHeader(CONTENT_TYPE)).isEqualTo("application/x-www-form-urlencoded");
assertThat(request.getBody().readUtf8()).contains("name+1=value+1", "name+2=value+2%2B1", "name+2=value+2%2B2");
return new MockResponse().setResponseCode(200);
assertThat(request.getHeaders().get(CONTENT_TYPE)).isEqualTo("application/x-www-form-urlencoded");
assertThat(request.getBody().utf8()).contains("name+1=value+1", "name+2=value+2%2B1", "name+2=value+2%2B2");
return new MockResponse.Builder().code(200).build();
}
private MockResponse patchRequest(RecordedRequest request, String expectedRequestContent,
String contentType, byte[] responseBody) {
assertThat(request.getMethod()).isEqualTo("PATCH");
assertThat(Integer.parseInt(request.getHeader(CONTENT_LENGTH))).as("Invalid request content-length").isGreaterThan(0);
String requestContentType = request.getHeader(CONTENT_TYPE);
assertThat(Integer.parseInt(request.getHeaders().get(CONTENT_LENGTH))).as("Invalid request content-length").isGreaterThan(0);
String requestContentType = request.getHeaders().get(CONTENT_TYPE);
assertThat(requestContentType).as("No content-type").isNotNull();
Charset charset = StandardCharsets.ISO_8859_1;
if (requestContentType.contains("charset=")) {
String charsetName = requestContentType.split("charset=")[1];
charset = Charset.forName(charsetName);
}
assertThat(request.getBody().readString(charset)).as("Invalid request body").isEqualTo(expectedRequestContent);
assertThat(request.getBody().string(charset)).as("Invalid request body").isEqualTo(expectedRequestContent);
Buffer buf = new Buffer();
buf.write(responseBody);
return new MockResponse().setResponseCode(201)
return new MockResponse.Builder()
.code(201)
.setHeader(CONTENT_LENGTH, responseBody.length)
.setHeader(CONTENT_TYPE, contentType)
.setBody(buf);
.body(buf)
.build();
}
private MockResponse putRequest(RecordedRequest request, String expectedRequestContent) {
assertThat(Integer.parseInt(request.getHeader(CONTENT_LENGTH))).as("Invalid request content-length").isGreaterThan(0);
String requestContentType = request.getHeader(CONTENT_TYPE);
assertThat(Integer.parseInt(request.getHeaders().get(CONTENT_LENGTH))).as("Invalid request content-length").isGreaterThan(0);
String requestContentType = request.getHeaders().get(CONTENT_TYPE);
assertThat(requestContentType).as("No content-type").isNotNull();
Charset charset = StandardCharsets.ISO_8859_1;
if (requestContentType.contains("charset=")) {
String charsetName = requestContentType.split("charset=")[1];
charset = Charset.forName(charsetName);
}
assertThat(request.getBody().readString(charset)).as("Invalid request body").isEqualTo(expectedRequestContent);
return new MockResponse().setResponseCode(202);
assertThat(request.getBody().string(charset)).as("Invalid request body").isEqualTo(expectedRequestContent);
return new MockResponse.Builder().code(202).build();
}
@ -239,64 +248,64 @@ abstract class AbstractMockWebServerTests { @@ -239,64 +248,64 @@ abstract class AbstractMockWebServerTests {
try {
byte[] helloWorldBytes = helloWorld.getBytes(StandardCharsets.UTF_8);
if (request.getPath().equals("/get")) {
if (request.getTarget().equals("/get")) {
return getRequest(request, helloWorldBytes, textContentType.toString());
}
else if (request.getPath().equals("/get/nothing")) {
else if (request.getTarget().equals("/get/nothing")) {
return getRequest(request, new byte[0], textContentType.toString());
}
else if (request.getPath().equals("/get/nocontenttype")) {
else if (request.getTarget().equals("/get/nocontenttype")) {
return getRequest(request, helloWorldBytes, null);
}
else if (request.getPath().equals("/post")) {
else if (request.getTarget().equals("/post")) {
return postRequest(request, helloWorld, "/post/1", textContentType.toString(), helloWorldBytes);
}
else if (request.getPath().equals("/jsonpost")) {
else if (request.getTarget().equals("/jsonpost")) {
return jsonPostRequest(request, "/jsonpost/1", "application/json; charset=utf-8");
}
else if (request.getPath().equals("/status/nocontent")) {
return new MockResponse().setResponseCode(204);
else if (request.getTarget().equals("/status/nocontent")) {
return new MockResponse.Builder().code(204).build();
}
else if (request.getPath().equals("/status/notmodified")) {
return new MockResponse().setResponseCode(304);
else if (request.getTarget().equals("/status/notmodified")) {
return new MockResponse.Builder().code(304).build();
}
else if (request.getPath().equals("/status/notfound")) {
return new MockResponse().setResponseCode(404);
else if (request.getTarget().equals("/status/notfound")) {
return new MockResponse.Builder().code(404).build();
}
else if (request.getPath().equals("/status/badrequest")) {
return new MockResponse().setResponseCode(400);
else if (request.getTarget().equals("/status/badrequest")) {
return new MockResponse.Builder().code(400).build();
}
else if (request.getPath().equals("/status/server")) {
return new MockResponse().setResponseCode(500);
else if (request.getTarget().equals("/status/server")) {
return new MockResponse.Builder().code(500).build();
}
else if (request.getPath().contains("/uri/")) {
return new MockResponse().setBody(request.getPath()).setHeader(CONTENT_TYPE, "text/plain");
else if (request.getTarget().contains("/uri/")) {
return new MockResponse.Builder().body(request.getTarget()).setHeader(CONTENT_TYPE, "text/plain").build();
}
else if (request.getPath().equals("/multipartFormData")) {
else if (request.getTarget().equals("/multipartFormData")) {
return multipartFormDataRequest(request);
}
else if (request.getPath().equals("/multipartMixed")) {
else if (request.getTarget().equals("/multipartMixed")) {
return multipartMixedRequest(request);
}
else if (request.getPath().equals("/multipartRelated")) {
else if (request.getTarget().equals("/multipartRelated")) {
return multipartRelatedRequest(request);
}
else if (request.getPath().equals("/form")) {
else if (request.getTarget().equals("/form")) {
return formRequest(request);
}
else if (request.getPath().equals("/delete")) {
return new MockResponse().setResponseCode(200);
else if (request.getTarget().equals("/delete")) {
return new MockResponse.Builder().code(200).build();
}
else if (request.getPath().equals("/patch")) {
else if (request.getTarget().equals("/patch")) {
return patchRequest(request, helloWorld, textContentType.toString(), helloWorldBytes);
}
else if (request.getPath().equals("/put")) {
else if (request.getTarget().equals("/put")) {
return putRequest(request, helloWorld);
}
return new MockResponse().setResponseCode(404);
return new MockResponse.Builder().code(404).build();
}
catch (Throwable ex) {
return new MockResponse().setResponseCode(500).setBody(ex.toString());
return new MockResponse.Builder().code(500).body(ex.toString()).build();
}
}
}

412
spring-web/src/test/java/org/springframework/web/client/RestClientIntegrationTests.java

@ -27,12 +27,13 @@ import java.net.URISyntaxException; @@ -27,12 +27,13 @@ import java.net.URISyntaxException;
import java.util.List;
import java.util.Map;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.stream.Stream;
import com.fasterxml.jackson.annotation.JsonView;
import okhttp3.mockwebserver.MockResponse;
import okhttp3.mockwebserver.MockWebServer;
import okhttp3.mockwebserver.RecordedRequest;
import mockwebserver3.MockResponse;
import mockwebserver3.MockWebServer;
import mockwebserver3.RecordedRequest;
import org.jspecify.annotations.Nullable;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.params.ParameterizedTest;
@ -99,8 +100,9 @@ class RestClientIntegrationTests { @@ -99,8 +100,9 @@ class RestClientIntegrationTests {
private RestClient restClient;
private void startServer(ClientHttpRequestFactory requestFactory) {
private void startServer(ClientHttpRequestFactory requestFactory) throws IOException {
this.server = new MockWebServer();
this.server.start();
this.restClient = RestClient
.builder()
.requestFactory(requestFactory)
@ -111,17 +113,17 @@ class RestClientIntegrationTests { @@ -111,17 +113,17 @@ class RestClientIntegrationTests {
@AfterEach
void shutdown() throws IOException {
if (server != null) {
this.server.shutdown();
this.server.close();
}
}
@ParameterizedRestClientTest
void retrieve(ClientHttpRequestFactory requestFactory) {
void retrieve(ClientHttpRequestFactory requestFactory) throws IOException {
startServer(requestFactory);
prepareResponse(response ->
response.setHeader("Content-Type", "text/plain").setBody("Hello Spring!"));
prepareResponse(builder -> builder
.setHeader("Content-Type", "text/plain").body("Hello Spring!"));
String result = this.restClient.get()
.uri("/greeting")
@ -133,18 +135,18 @@ class RestClientIntegrationTests { @@ -133,18 +135,18 @@ class RestClientIntegrationTests {
expectRequestCount(1);
expectRequest(request -> {
assertThat(request.getHeader("X-Test-Header")).isEqualTo("testvalue");
assertThat(request.getPath()).isEqualTo("/greeting");
assertThat(request.getHeaders().get("X-Test-Header")).isEqualTo("testvalue");
assertThat(request.getTarget()).isEqualTo("/greeting");
});
}
@ParameterizedRestClientTest
void retrieveJson(ClientHttpRequestFactory requestFactory) {
void retrieveJson(ClientHttpRequestFactory requestFactory) throws IOException {
startServer(requestFactory);
prepareResponse(response -> response
prepareResponse(builder -> builder
.setHeader("Content-Type", "application/json")
.setBody("{\"bar\":\"barbar\",\"foo\":\"foofoo\"}"));
.body("{\"bar\":\"barbar\",\"foo\":\"foofoo\"}"));
Pojo result = this.restClient.get()
.uri("/pojo")
@ -157,18 +159,18 @@ class RestClientIntegrationTests { @@ -157,18 +159,18 @@ class RestClientIntegrationTests {
expectRequestCount(1);
expectRequest(request -> {
assertThat(request.getPath()).isEqualTo("/pojo");
assertThat(request.getHeader(HttpHeaders.ACCEPT)).isEqualTo("application/json");
assertThat(request.getTarget()).isEqualTo("/pojo");
assertThat(request.getHeaders().get(HttpHeaders.ACCEPT)).isEqualTo("application/json");
});
}
@ParameterizedRestClientTest
void retrieveJsonWithParameterizedTypeReference(ClientHttpRequestFactory requestFactory) {
void retrieveJsonWithParameterizedTypeReference(ClientHttpRequestFactory requestFactory) throws IOException {
startServer(requestFactory);
String content = "{\"containerValue\":{\"bar\":\"barbar\",\"foo\":\"foofoo\"}}";
prepareResponse(response -> response
.setHeader("Content-Type", "application/json").setBody(content));
prepareResponse(builder -> builder
.setHeader("Content-Type", "application/json").body(content));
ValueContainer<Pojo> result = this.restClient.get()
.uri("/json").accept(MediaType.APPLICATION_JSON)
@ -182,18 +184,18 @@ class RestClientIntegrationTests { @@ -182,18 +184,18 @@ class RestClientIntegrationTests {
expectRequestCount(1);
expectRequest(request -> {
assertThat(request.getPath()).isEqualTo("/json");
assertThat(request.getHeader(HttpHeaders.ACCEPT)).isEqualTo("application/json");
assertThat(request.getTarget()).isEqualTo("/json");
assertThat(request.getHeaders().get(HttpHeaders.ACCEPT)).isEqualTo("application/json");
});
}
@ParameterizedRestClientTest
void retrieveJsonWithListParameterizedTypeReference(ClientHttpRequestFactory requestFactory) {
void retrieveJsonWithListParameterizedTypeReference(ClientHttpRequestFactory requestFactory) throws IOException {
startServer(requestFactory);
String content = "{\"containerValue\":[{\"bar\":\"barbar\",\"foo\":\"foofoo\"}]}";
prepareResponse(response -> response
.setHeader("Content-Type", "application/json").setBody(content));
prepareResponse(builder -> builder
.setHeader("Content-Type", "application/json").body(content));
ValueContainer<List<Pojo>> result = this.restClient.get()
.uri("/json").accept(MediaType.APPLICATION_JSON)
@ -205,18 +207,18 @@ class RestClientIntegrationTests { @@ -205,18 +207,18 @@ class RestClientIntegrationTests {
expectRequestCount(1);
expectRequest(request -> {
assertThat(request.getPath()).isEqualTo("/json");
assertThat(request.getHeader(HttpHeaders.ACCEPT)).isEqualTo("application/json");
assertThat(request.getTarget()).isEqualTo("/json");
assertThat(request.getHeaders().get(HttpHeaders.ACCEPT)).isEqualTo("application/json");
});
}
@ParameterizedRestClientTest
void retrieveJsonAsResponseEntity(ClientHttpRequestFactory requestFactory) {
void retrieveJsonAsResponseEntity(ClientHttpRequestFactory requestFactory) throws IOException {
startServer(requestFactory);
String content = "{\"bar\":\"barbar\",\"foo\":\"foofoo\"}";
prepareResponse(response -> response
.setHeader("Content-Type", "application/json").setBody(content));
prepareResponse(builder -> builder
.setHeader("Content-Type", "application/json").body(content));
ResponseEntity<String> result = this.restClient.get()
.uri("/json").accept(MediaType.APPLICATION_JSON)
@ -230,17 +232,17 @@ class RestClientIntegrationTests { @@ -230,17 +232,17 @@ class RestClientIntegrationTests {
expectRequestCount(1);
expectRequest(request -> {
assertThat(request.getPath()).isEqualTo("/json");
assertThat(request.getHeader(HttpHeaders.ACCEPT)).isEqualTo("application/json");
assertThat(request.getTarget()).isEqualTo("/json");
assertThat(request.getHeaders().get(HttpHeaders.ACCEPT)).isEqualTo("application/json");
});
}
@ParameterizedRestClientTest
void retrieveJsonAsBodilessEntity(ClientHttpRequestFactory requestFactory) {
void retrieveJsonAsBodilessEntity(ClientHttpRequestFactory requestFactory) throws IOException {
startServer(requestFactory);
prepareResponse(response -> response
.setHeader("Content-Type", "application/json").setBody("{\"bar\":\"barbar\",\"foo\":\"foofoo\"}"));
prepareResponse(builder -> builder
.setHeader("Content-Type", "application/json").body("{\"bar\":\"barbar\",\"foo\":\"foofoo\"}"));
ResponseEntity<Void> result = this.restClient.get()
.uri("/json").accept(MediaType.APPLICATION_JSON)
@ -254,18 +256,18 @@ class RestClientIntegrationTests { @@ -254,18 +256,18 @@ class RestClientIntegrationTests {
expectRequestCount(1);
expectRequest(request -> {
assertThat(request.getPath()).isEqualTo("/json");
assertThat(request.getHeader(HttpHeaders.ACCEPT)).isEqualTo("application/json");
assertThat(request.getTarget()).isEqualTo("/json");
assertThat(request.getHeaders().get(HttpHeaders.ACCEPT)).isEqualTo("application/json");
});
}
@ParameterizedRestClientTest
void retrieveJsonArray(ClientHttpRequestFactory requestFactory) {
void retrieveJsonArray(ClientHttpRequestFactory requestFactory) throws IOException {
startServer(requestFactory);
prepareResponse(response -> response
prepareResponse(builder -> builder
.setHeader("Content-Type", "application/json")
.setBody("[{\"bar\":\"bar1\",\"foo\":\"foo1\"},{\"bar\":\"bar2\",\"foo\":\"foo2\"}]"));
.body("[{\"bar\":\"bar1\",\"foo\":\"foo1\"},{\"bar\":\"bar2\",\"foo\":\"foo2\"}]"));
List<Pojo> result = this.restClient.get()
.uri("/pojos")
@ -281,18 +283,18 @@ class RestClientIntegrationTests { @@ -281,18 +283,18 @@ class RestClientIntegrationTests {
expectRequestCount(1);
expectRequest(request -> {
assertThat(request.getPath()).isEqualTo("/pojos");
assertThat(request.getHeader(HttpHeaders.ACCEPT)).isEqualTo("application/json");
assertThat(request.getTarget()).isEqualTo("/pojos");
assertThat(request.getHeaders().get(HttpHeaders.ACCEPT)).isEqualTo("application/json");
});
}
@ParameterizedRestClientTest
void retrieveJsonArrayAsResponseEntityList(ClientHttpRequestFactory requestFactory) {
void retrieveJsonArrayAsResponseEntityList(ClientHttpRequestFactory requestFactory) throws IOException {
startServer(requestFactory);
String content = "[{\"bar\":\"bar1\",\"foo\":\"foo1\"}, {\"bar\":\"bar2\",\"foo\":\"foo2\"}]";
prepareResponse(response -> response
.setHeader("Content-Type", "application/json").setBody(content));
prepareResponse(builder -> builder
.setHeader("Content-Type", "application/json").body(content));
ResponseEntity<List<Pojo>> result = this.restClient.get()
.uri("/json").accept(MediaType.APPLICATION_JSON)
@ -310,18 +312,18 @@ class RestClientIntegrationTests { @@ -310,18 +312,18 @@ class RestClientIntegrationTests {
expectRequestCount(1);
expectRequest(request -> {
assertThat(request.getPath()).isEqualTo("/json");
assertThat(request.getHeader(HttpHeaders.ACCEPT)).isEqualTo("application/json");
assertThat(request.getTarget()).isEqualTo("/json");
assertThat(request.getHeaders().get(HttpHeaders.ACCEPT)).isEqualTo("application/json");
});
}
@ParameterizedRestClientTest
void retrieveJsonAsSerializedText(ClientHttpRequestFactory requestFactory) {
void retrieveJsonAsSerializedText(ClientHttpRequestFactory requestFactory) throws IOException {
startServer(requestFactory);
String content = "{\"bar\":\"barbar\",\"foo\":\"foofoo\"}";
prepareResponse(response -> response
.setHeader("Content-Type", "application/json").setBody(content));
prepareResponse(builder -> builder
.setHeader("Content-Type", "application/json").body(content));
String result = this.restClient.get()
.uri("/json").accept(MediaType.APPLICATION_JSON)
@ -332,20 +334,20 @@ class RestClientIntegrationTests { @@ -332,20 +334,20 @@ class RestClientIntegrationTests {
expectRequestCount(1);
expectRequest(request -> {
assertThat(request.getPath()).isEqualTo("/json");
assertThat(request.getHeader(HttpHeaders.ACCEPT)).isEqualTo("application/json");
assertThat(request.getTarget()).isEqualTo("/json");
assertThat(request.getHeaders().get(HttpHeaders.ACCEPT)).isEqualTo("application/json");
});
}
@ParameterizedRestClientTest
@SuppressWarnings({ "rawtypes", "unchecked" })
void retrieveJsonNull(ClientHttpRequestFactory requestFactory) {
void retrieveJsonNull(ClientHttpRequestFactory requestFactory) throws IOException {
startServer(requestFactory);
prepareResponse(response -> response
.setResponseCode(200)
prepareResponse(builder -> builder
.code(200)
.setHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE)
.setBody("null"));
.body("null"));
Map result = this.restClient.get()
.uri("/null")
@ -356,11 +358,11 @@ class RestClientIntegrationTests { @@ -356,11 +358,11 @@ class RestClientIntegrationTests {
}
@ParameterizedRestClientTest
void retrieveJsonEmpty(ClientHttpRequestFactory requestFactory) {
void retrieveJsonEmpty(ClientHttpRequestFactory requestFactory) throws IOException {
startServer(requestFactory);
prepareResponse(response -> response
.setResponseCode(200)
prepareResponse(builder -> builder
.code(200)
.setHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE));
Pojo result = this.restClient.get()
@ -372,11 +374,10 @@ class RestClientIntegrationTests { @@ -372,11 +374,10 @@ class RestClientIntegrationTests {
}
@ParameterizedRestClientTest
void retrieve404(ClientHttpRequestFactory requestFactory) {
void retrieve404(ClientHttpRequestFactory requestFactory) throws IOException {
startServer(requestFactory);
prepareResponse(response -> response.setResponseCode(404)
.setHeader("Content-Type", "text/plain"));
prepareResponse(builder -> builder.code(404).setHeader("Content-Type", "text/plain"));
assertThatExceptionOfType(HttpClientErrorException.NotFound.class).isThrownBy(() ->
this.restClient.get().uri("/greeting")
@ -385,16 +386,16 @@ class RestClientIntegrationTests { @@ -385,16 +386,16 @@ class RestClientIntegrationTests {
);
expectRequestCount(1);
expectRequest(request -> assertThat(request.getPath()).isEqualTo("/greeting"));
expectRequest(request -> assertThat(request.getTarget()).isEqualTo("/greeting"));
}
@ParameterizedRestClientTest
void retrieve404WithBody(ClientHttpRequestFactory requestFactory) {
void retrieve404WithBody(ClientHttpRequestFactory requestFactory) throws IOException {
startServer(requestFactory);
prepareResponse(response -> response.setResponseCode(404)
.setHeader("Content-Type", "text/plain").setBody("Not Found"));
prepareResponse(builder -> builder.code(404)
.setHeader("Content-Type", "text/plain").body("Not Found"));
assertThatExceptionOfType(HttpClientErrorException.NotFound.class).isThrownBy(() ->
this.restClient.get()
@ -404,16 +405,16 @@ class RestClientIntegrationTests { @@ -404,16 +405,16 @@ class RestClientIntegrationTests {
);
expectRequestCount(1);
expectRequest(request -> assertThat(request.getPath()).isEqualTo("/greeting"));
expectRequest(request -> assertThat(request.getTarget()).isEqualTo("/greeting"));
}
@ParameterizedRestClientTest
void retrieve500(ClientHttpRequestFactory requestFactory) {
void retrieve500(ClientHttpRequestFactory requestFactory) throws IOException {
startServer(requestFactory);
String errorMessage = "Internal Server error";
prepareResponse(response -> response.setResponseCode(500)
.setHeader("Content-Type", "text/plain").setBody(errorMessage));
prepareResponse(builder -> builder.code(500)
.setHeader("Content-Type", "text/plain").body(errorMessage));
String path = "/greeting";
try {
@ -431,15 +432,15 @@ class RestClientIntegrationTests { @@ -431,15 +432,15 @@ class RestClientIntegrationTests {
}
expectRequestCount(1);
expectRequest(request -> assertThat(request.getPath()).isEqualTo(path));
expectRequest(request -> assertThat(request.getTarget()).isEqualTo(path));
}
@ParameterizedRestClientTest
void retrieve500AsEntity(ClientHttpRequestFactory requestFactory) {
void retrieve500AsEntity(ClientHttpRequestFactory requestFactory) throws IOException {
startServer(requestFactory);
prepareResponse(response -> response.setResponseCode(500)
.setHeader("Content-Type", "text/plain").setBody("Internal Server error"));
prepareResponse(builder -> builder.code(500)
.setHeader("Content-Type", "text/plain").body("Internal Server error"));
assertThatExceptionOfType(HttpServerErrorException.InternalServerError.class).isThrownBy(() ->
this.restClient.get()
@ -450,17 +451,17 @@ class RestClientIntegrationTests { @@ -450,17 +451,17 @@ class RestClientIntegrationTests {
expectRequestCount(1);
expectRequest(request -> {
assertThat(request.getPath()).isEqualTo("/");
assertThat(request.getHeader(HttpHeaders.ACCEPT)).isEqualTo("application/json");
assertThat(request.getTarget()).isEqualTo("/");
assertThat(request.getHeaders().get(HttpHeaders.ACCEPT)).isEqualTo("application/json");
});
}
@ParameterizedRestClientTest
void retrieve500AsBodilessEntity(ClientHttpRequestFactory requestFactory) {
void retrieve500AsBodilessEntity(ClientHttpRequestFactory requestFactory) throws IOException {
startServer(requestFactory);
prepareResponse(response -> response.setResponseCode(500)
.setHeader("Content-Type", "text/plain").setBody("Internal Server error"));
prepareResponse(builder -> builder.code(500)
.setHeader("Content-Type", "text/plain").body("Internal Server error"));
assertThatExceptionOfType(HttpServerErrorException.InternalServerError.class).isThrownBy(() ->
this.restClient.get()
@ -471,20 +472,20 @@ class RestClientIntegrationTests { @@ -471,20 +472,20 @@ class RestClientIntegrationTests {
expectRequestCount(1);
expectRequest(request -> {
assertThat(request.getPath()).isEqualTo("/");
assertThat(request.getHeader(HttpHeaders.ACCEPT)).isEqualTo("application/json");
assertThat(request.getTarget()).isEqualTo("/");
assertThat(request.getHeaders().get(HttpHeaders.ACCEPT)).isEqualTo("application/json");
});
}
@ParameterizedRestClientTest
void retrieve555UnknownStatus(ClientHttpRequestFactory requestFactory) {
void retrieve555UnknownStatus(ClientHttpRequestFactory requestFactory) throws IOException {
startServer(requestFactory);
int errorStatus = 555;
assertThat(HttpStatus.resolve(errorStatus)).isNull();
String errorMessage = "Something went wrong";
prepareResponse(response -> response.setResponseCode(errorStatus)
.setHeader("Content-Type", "text/plain").setBody(errorMessage));
prepareResponse(builder -> builder.code(errorStatus)
.setHeader("Content-Type", "text/plain").body(errorMessage));
try {
this.restClient.get()
@ -502,15 +503,15 @@ class RestClientIntegrationTests { @@ -502,15 +503,15 @@ class RestClientIntegrationTests {
}
expectRequestCount(1);
expectRequest(request -> assertThat(request.getPath()).isEqualTo("/unknownPage"));
expectRequest(request -> assertThat(request.getTarget()).isEqualTo("/unknownPage"));
}
@ParameterizedRestClientTest
void postPojoAsJson(ClientHttpRequestFactory requestFactory) {
void postPojoAsJson(ClientHttpRequestFactory requestFactory) throws IOException {
startServer(requestFactory);
prepareResponse(response -> response.setHeader("Content-Type", "application/json")
.setBody("{\"bar\":\"BARBAR\",\"foo\":\"FOOFOO\"}"));
prepareResponse(builder -> builder.setHeader("Content-Type", "application/json")
.body("{\"bar\":\"BARBAR\",\"foo\":\"FOOFOO\"}"));
Pojo result = this.restClient.post()
.uri("/pojo/capitalize")
@ -526,19 +527,19 @@ class RestClientIntegrationTests { @@ -526,19 +527,19 @@ class RestClientIntegrationTests {
expectRequestCount(1);
expectRequest(request -> {
assertThat(request.getPath()).isEqualTo("/pojo/capitalize");
assertThat(request.getBody().readUtf8()).isEqualTo("{\"bar\":\"barbar\",\"foo\":\"foofoo\"}");
assertThat(request.getHeader(HttpHeaders.ACCEPT)).isEqualTo("application/json");
assertThat(request.getHeader(HttpHeaders.CONTENT_TYPE)).isEqualTo("application/json");
assertThat(request.getTarget()).isEqualTo("/pojo/capitalize");
assertThat(request.getBody().utf8()).isEqualTo("{\"bar\":\"barbar\",\"foo\":\"foofoo\"}");
assertThat(request.getHeaders().get(HttpHeaders.ACCEPT)).isEqualTo("application/json");
assertThat(request.getHeaders().get(HttpHeaders.CONTENT_TYPE)).isEqualTo("application/json");
});
}
@ParameterizedRestClientTest
void postUserAsJsonWithJsonView(ClientHttpRequestFactory requestFactory) {
void postUserAsJsonWithJsonView(ClientHttpRequestFactory requestFactory) throws IOException {
startServer(requestFactory);
prepareResponse(response -> response.setHeader("Content-Type", "application/json")
.setBody("{\"username\":\"USERNAME\"}"));
prepareResponse(builder -> builder.setHeader("Content-Type", "application/json")
.body("{\"username\":\"USERNAME\"}"));
User result = this.restClient.post()
.uri("/user/capitalize")
@ -555,18 +556,18 @@ class RestClientIntegrationTests { @@ -555,18 +556,18 @@ class RestClientIntegrationTests {
expectRequestCount(1);
expectRequest(request -> {
assertThat(request.getPath()).isEqualTo("/user/capitalize");
assertThat(request.getBody().readUtf8()).isEqualTo("{\"username\":\"username\"}");
assertThat(request.getHeader(HttpHeaders.ACCEPT)).isEqualTo("application/json");
assertThat(request.getHeader(HttpHeaders.CONTENT_TYPE)).isEqualTo("application/json");
assertThat(request.getTarget()).isEqualTo("/user/capitalize");
assertThat(request.getBody().utf8()).isEqualTo("{\"username\":\"username\"}");
assertThat(request.getHeaders().get(HttpHeaders.ACCEPT)).isEqualTo("application/json");
assertThat(request.getHeaders().get(HttpHeaders.CONTENT_TYPE)).isEqualTo("application/json");
});
}
@ParameterizedRestClientTest // gh-31361
public void postForm(ClientHttpRequestFactory requestFactory) {
public void postForm(ClientHttpRequestFactory requestFactory) throws IOException {
startServer(requestFactory);
prepareResponse(response -> response.setResponseCode(200));
prepareResponse(builder -> builder.code(200));
MultiValueMap<String, String> formData = new LinkedMultiValueMap<>();
formData.add("foo", "bar");
@ -583,10 +584,10 @@ class RestClientIntegrationTests { @@ -583,10 +584,10 @@ class RestClientIntegrationTests {
expectRequestCount(1);
expectRequest(request -> {
assertThat(request.getPath()).isEqualTo("/form");
String contentType = request.getHeader(HttpHeaders.CONTENT_TYPE);
assertThat(request.getTarget()).isEqualTo("/form");
String contentType = request.getHeaders().get(HttpHeaders.CONTENT_TYPE);
assertThat(contentType).startsWith(MediaType.MULTIPART_FORM_DATA_VALUE);
String[] lines = request.getBody().readUtf8().split("\r\n");
String[] lines = request.getBody().utf8().split("\r\n");
assertThat(lines).hasSize(13);
assertThat(lines[0]).startsWith("--"); // boundary
assertThat(lines[1]).isEqualTo("Content-Disposition: form-data; name=\"foo\"");
@ -606,9 +607,9 @@ class RestClientIntegrationTests { @@ -606,9 +607,9 @@ class RestClientIntegrationTests {
}
@ParameterizedRestClientTest // gh-35102
void postStreamingBody(ClientHttpRequestFactory requestFactory) {
void postStreamingBody(ClientHttpRequestFactory requestFactory) throws IOException {
startServer(requestFactory);
prepareResponse(response -> response.setResponseCode(200));
prepareResponse(builder -> builder.code(200));
StreamingHttpOutputMessage.Body testBody = out -> {
assertThat(out).as("Not a streaming response").isNotInstanceOf(FastByteArrayOutputStream.class);
@ -625,17 +626,17 @@ class RestClientIntegrationTests { @@ -625,17 +626,17 @@ class RestClientIntegrationTests {
expectRequestCount(1);
expectRequest(request -> {
assertThat(request.getPath()).isEqualTo("/streaming/body");
assertThat(request.getBody().readUtf8()).isEqualTo("test-data");
assertThat(request.getTarget()).isEqualTo("/streaming/body");
assertThat(request.getBody().utf8()).isEqualTo("test-data");
});
}
@ParameterizedRestClientTest
void statusHandler(ClientHttpRequestFactory requestFactory) {
void statusHandler(ClientHttpRequestFactory requestFactory) throws IOException {
startServer(requestFactory);
prepareResponse(response -> response.setResponseCode(500)
.setHeader("Content-Type", "text/plain").setBody("Internal Server error"));
prepareResponse(builder -> builder.code(500)
.setHeader("Content-Type", "text/plain").body("Internal Server error"));
assertThatExceptionOfType(MyException.class).isThrownBy(() ->
this.restClient.get()
@ -648,15 +649,15 @@ class RestClientIntegrationTests { @@ -648,15 +649,15 @@ class RestClientIntegrationTests {
);
expectRequestCount(1);
expectRequest(request -> assertThat(request.getPath()).isEqualTo("/greeting"));
expectRequest(request -> assertThat(request.getTarget()).isEqualTo("/greeting"));
}
@ParameterizedRestClientTest
void statusHandlerIOException(ClientHttpRequestFactory requestFactory) {
void statusHandlerIOException(ClientHttpRequestFactory requestFactory) throws IOException {
startServer(requestFactory);
prepareResponse(response -> response.setResponseCode(500)
.setHeader("Content-Type", "text/plain").setBody("Internal Server error"));
prepareResponse(builder -> builder.code(500)
.setHeader("Content-Type", "text/plain").body("Internal Server error"));
assertThatExceptionOfType(RestClientException.class).isThrownBy(() ->
this.restClient.get()
@ -669,15 +670,15 @@ class RestClientIntegrationTests { @@ -669,15 +670,15 @@ class RestClientIntegrationTests {
).withCauseInstanceOf(IOException.class);
expectRequestCount(1);
expectRequest(request -> assertThat(request.getPath()).isEqualTo("/greeting"));
expectRequest(request -> assertThat(request.getTarget()).isEqualTo("/greeting"));
}
@ParameterizedRestClientTest
void statusHandlerParameterizedTypeReference(ClientHttpRequestFactory requestFactory) {
void statusHandlerParameterizedTypeReference(ClientHttpRequestFactory requestFactory) throws IOException {
startServer(requestFactory);
prepareResponse(response -> response.setResponseCode(500)
.setHeader("Content-Type", "text/plain").setBody("Internal Server error"));
prepareResponse(builder -> builder.code(500)
.setHeader("Content-Type", "text/plain").body("Internal Server error"));
assertThatExceptionOfType(MyException.class).isThrownBy(() ->
this.restClient.get()
@ -691,15 +692,15 @@ class RestClientIntegrationTests { @@ -691,15 +692,15 @@ class RestClientIntegrationTests {
);
expectRequestCount(1);
expectRequest(request -> assertThat(request.getPath()).isEqualTo("/greeting"));
expectRequest(request -> assertThat(request.getTarget()).isEqualTo("/greeting"));
}
@ParameterizedRestClientTest
void statusHandlerSuppressedErrorSignal(ClientHttpRequestFactory requestFactory) {
void statusHandlerSuppressedErrorSignal(ClientHttpRequestFactory requestFactory) throws IOException {
startServer(requestFactory);
prepareResponse(response -> response.setResponseCode(500)
.setHeader("Content-Type", "text/plain").setBody("Internal Server error"));
prepareResponse(builder -> builder.code(500)
.setHeader("Content-Type", "text/plain").body("Internal Server error"));
String result = this.restClient.get()
.uri("/greeting")
@ -710,16 +711,16 @@ class RestClientIntegrationTests { @@ -710,16 +711,16 @@ class RestClientIntegrationTests {
assertThat(result).isEqualTo("Internal Server error");
expectRequestCount(1);
expectRequest(request -> assertThat(request.getPath()).isEqualTo("/greeting"));
expectRequest(request -> assertThat(request.getTarget()).isEqualTo("/greeting"));
}
@ParameterizedRestClientTest
void statusHandlerSuppressedErrorSignalWithEntity(ClientHttpRequestFactory requestFactory) {
void statusHandlerSuppressedErrorSignalWithEntity(ClientHttpRequestFactory requestFactory) throws IOException {
startServer(requestFactory);
String content = "Internal Server error";
prepareResponse(response ->
response.setResponseCode(500).setHeader("Content-Type", "text/plain").setBody(content));
prepareResponse(builder -> builder.code(500)
.setHeader("Content-Type", "text/plain").body(content));
ResponseEntity<String> result = this.restClient.get()
.uri("/").accept(MediaType.APPLICATION_JSON)
@ -733,16 +734,16 @@ class RestClientIntegrationTests { @@ -733,16 +734,16 @@ class RestClientIntegrationTests {
expectRequestCount(1);
expectRequest(request -> {
assertThat(request.getPath()).isEqualTo("/");
assertThat(request.getHeader(HttpHeaders.ACCEPT)).isEqualTo("application/json");
assertThat(request.getTarget()).isEqualTo("/");
assertThat(request.getHeaders().get(HttpHeaders.ACCEPT)).isEqualTo("application/json");
});
}
@ParameterizedRestClientTest
void exchangeForPlainText(ClientHttpRequestFactory requestFactory) {
void exchangeForPlainText(ClientHttpRequestFactory requestFactory) throws IOException {
startServer(requestFactory);
prepareResponse(response -> response.setBody("Hello Spring!"));
prepareResponse(builder -> builder.body("Hello Spring!"));
String result = this.restClient.get()
.uri("/greeting")
@ -753,18 +754,18 @@ class RestClientIntegrationTests { @@ -753,18 +754,18 @@ class RestClientIntegrationTests {
expectRequestCount(1);
expectRequest(request -> {
assertThat(request.getHeader("X-Test-Header")).isEqualTo("testvalue");
assertThat(request.getPath()).isEqualTo("/greeting");
assertThat(request.getHeaders().get("X-Test-Header")).isEqualTo("testvalue");
assertThat(request.getTarget()).isEqualTo("/greeting");
});
}
@ParameterizedRestClientTest
void exchangeForJson(ClientHttpRequestFactory requestFactory) {
void exchangeForJson(ClientHttpRequestFactory requestFactory) throws IOException {
startServer(requestFactory);
prepareResponse(response -> response
prepareResponse(builder -> builder
.setHeader("Content-Type", "application/json")
.setBody("{\"bar\":\"barbar\",\"foo\":\"foofoo\"}"));
.body("{\"bar\":\"barbar\",\"foo\":\"foofoo\"}"));
Pojo result = this.restClient.get()
.uri("/pojo")
@ -776,18 +777,18 @@ class RestClientIntegrationTests { @@ -776,18 +777,18 @@ class RestClientIntegrationTests {
expectRequestCount(1);
expectRequest(request -> {
assertThat(request.getPath()).isEqualTo("/pojo");
assertThat(request.getHeader(HttpHeaders.ACCEPT)).isEqualTo("application/json");
assertThat(request.getTarget()).isEqualTo("/pojo");
assertThat(request.getHeaders().get(HttpHeaders.ACCEPT)).isEqualTo("application/json");
});
}
@ParameterizedRestClientTest
void exchangeForJsonArray(ClientHttpRequestFactory requestFactory) {
void exchangeForJsonArray(ClientHttpRequestFactory requestFactory) throws IOException {
startServer(requestFactory);
prepareResponse(response -> response
prepareResponse(builder -> builder
.setHeader("Content-Type", "application/json")
.setBody("[{\"bar\":\"bar1\",\"foo\":\"foo1\"},{\"bar\":\"bar2\",\"foo\":\"foo2\"}]"));
.body("[{\"bar\":\"bar1\",\"foo\":\"foo1\"},{\"bar\":\"bar2\",\"foo\":\"foo2\"}]"));
List<Pojo> result = this.restClient.get()
.uri("/pojo")
@ -802,17 +803,17 @@ class RestClientIntegrationTests { @@ -802,17 +803,17 @@ class RestClientIntegrationTests {
expectRequestCount(1);
expectRequest(request -> {
assertThat(request.getPath()).isEqualTo("/pojo");
assertThat(request.getHeader(HttpHeaders.ACCEPT)).isEqualTo("application/json");
assertThat(request.getTarget()).isEqualTo("/pojo");
assertThat(request.getHeaders().get(HttpHeaders.ACCEPT)).isEqualTo("application/json");
});
}
@ParameterizedRestClientTest
void exchangeFor404(ClientHttpRequestFactory requestFactory) {
void exchangeFor404(ClientHttpRequestFactory requestFactory) throws IOException {
startServer(requestFactory);
prepareResponse(response ->
response.setResponseCode(404).setHeader("Content-Type", "text/plain").setBody("Not Found"));
prepareResponse(builder ->
builder.code(404).setHeader("Content-Type", "text/plain").body("Not Found"));
String result = this.restClient.get()
.uri("/greeting")
@ -821,14 +822,14 @@ class RestClientIntegrationTests { @@ -821,14 +822,14 @@ class RestClientIntegrationTests {
assertThat(result).isEqualTo("Not Found");
expectRequestCount(1);
expectRequest(request -> assertThat(request.getPath()).isEqualTo("/greeting"));
expectRequest(request -> assertThat(request.getTarget()).isEqualTo("/greeting"));
}
@ParameterizedRestClientTest
void exchangeForRequiredValue(ClientHttpRequestFactory requestFactory) {
void exchangeForRequiredValue(ClientHttpRequestFactory requestFactory) throws IOException {
startServer(requestFactory);
prepareResponse(response -> response.setBody("Hello Spring!"));
prepareResponse(builder -> builder.body("Hello Spring!"));
String result = this.restClient.get()
.uri("/greeting")
@ -839,17 +840,17 @@ class RestClientIntegrationTests { @@ -839,17 +840,17 @@ class RestClientIntegrationTests {
expectRequestCount(1);
expectRequest(request -> {
assertThat(request.getHeader("X-Test-Header")).isEqualTo("testvalue");
assertThat(request.getPath()).isEqualTo("/greeting");
assertThat(request.getHeaders().get("X-Test-Header")).isEqualTo("testvalue");
assertThat(request.getTarget()).isEqualTo("/greeting");
});
}
@ParameterizedRestClientTest
@SuppressWarnings("DataFlowIssue")
void exchangeForNullRequiredValue(ClientHttpRequestFactory requestFactory) {
void exchangeForNullRequiredValue(ClientHttpRequestFactory requestFactory) throws IOException {
startServer(requestFactory);
prepareResponse(response -> response.setBody("Hello Spring!"));
prepareResponse(builder -> builder.body("Hello Spring!"));
assertThatIllegalStateException().isThrownBy(() -> this.restClient.get()
.uri("/greeting")
@ -858,11 +859,11 @@ class RestClientIntegrationTests { @@ -858,11 +859,11 @@ class RestClientIntegrationTests {
}
@ParameterizedRestClientTest
void requestInitializer(ClientHttpRequestFactory requestFactory) {
void requestInitializer(ClientHttpRequestFactory requestFactory) throws IOException {
startServer(requestFactory);
prepareResponse(response ->
response.setHeader("Content-Type", "text/plain").setBody("Hello Spring!"));
prepareResponse(builder ->
builder.setHeader("Content-Type", "text/plain").body("Hello Spring!"));
RestClient initializedClient = this.restClient.mutate()
.requestInitializer(request -> request.getHeaders().add("foo", "bar"))
@ -876,15 +877,15 @@ class RestClientIntegrationTests { @@ -876,15 +877,15 @@ class RestClientIntegrationTests {
assertThat(result).isEqualTo("Hello Spring!");
expectRequestCount(1);
expectRequest(request -> assertThat(request.getHeader("foo")).isEqualTo("bar"));
expectRequest(request -> assertThat(request.getHeaders().get("foo")).isEqualTo("bar"));
}
@ParameterizedRestClientTest
void requestInterceptor(ClientHttpRequestFactory requestFactory) {
void requestInterceptor(ClientHttpRequestFactory requestFactory) throws IOException {
startServer(requestFactory);
prepareResponse(response ->
response.setHeader("Content-Type", "text/plain").setBody("Hello Spring!"));
prepareResponse(builder ->
builder.setHeader("Content-Type", "text/plain").body("Hello Spring!"));
RestClient interceptedClient = this.restClient.mutate()
.requestInterceptor((request, body, execution) -> {
@ -901,15 +902,15 @@ class RestClientIntegrationTests { @@ -901,15 +902,15 @@ class RestClientIntegrationTests {
assertThat(result).isEqualTo("Hello Spring!");
expectRequestCount(1);
expectRequest(request -> assertThat(request.getHeader("foo")).isEqualTo("bar"));
expectRequest(request -> assertThat(request.getHeaders().get("foo")).isEqualTo("bar"));
}
@ParameterizedRestClientTest
void requestInterceptorWithResponseBuffering(ClientHttpRequestFactory requestFactory) {
void requestInterceptorWithResponseBuffering(ClientHttpRequestFactory requestFactory) throws IOException {
startServer(requestFactory);
prepareResponse(response ->
response.setHeader("Content-Type", "text/plain").setBody("Hello Spring!"));
prepareResponse(builder ->
builder.setHeader("Content-Type", "text/plain").body("Hello Spring!"));
RestClient interceptedClient = this.restClient.mutate()
.requestInterceptor((request, body, execution) -> {
@ -931,11 +932,11 @@ class RestClientIntegrationTests { @@ -931,11 +932,11 @@ class RestClientIntegrationTests {
}
@ParameterizedRestClientTest
void bufferContent(ClientHttpRequestFactory requestFactory) {
void bufferContent(ClientHttpRequestFactory requestFactory) throws IOException {
startServer(requestFactory);
prepareResponse(response ->
response.setHeader("Content-Type", "text/plain").setBody("Hello Spring!"));
prepareResponse(builder ->
builder.setHeader("Content-Type", "text/plain").body("Hello Spring!"));
RestClient bufferingClient = this.restClient.mutate()
.bufferContent((uri, httpMethod) -> true)
@ -956,10 +957,10 @@ class RestClientIntegrationTests { @@ -956,10 +957,10 @@ class RestClientIntegrationTests {
}
@ParameterizedRestClientTest
void retrieveDefaultCookiesAsCookieHeader(ClientHttpRequestFactory requestFactory) {
void retrieveDefaultCookiesAsCookieHeader(ClientHttpRequestFactory requestFactory) throws IOException {
startServer(requestFactory);
prepareResponse(response ->
response.setHeader("Content-Type", "text/plain").setBody("Hello Spring!"));
prepareResponse(builder ->
builder.setHeader("Content-Type", "text/plain").body("Hello Spring!"));
RestClient restClientWithCookies = this.restClient.mutate()
.defaultCookie("testCookie", "firstValue", "secondValue")
@ -972,13 +973,13 @@ class RestClientIntegrationTests { @@ -972,13 +973,13 @@ class RestClientIntegrationTests {
.body(String.class);
expectRequest(request ->
assertThat(request.getHeader(HttpHeaders.COOKIE))
assertThat(request.getHeaders().get(HttpHeaders.COOKIE))
.isEqualTo("testCookie=firstValue; testCookie=secondValue")
);
}
@ParameterizedRestClientTest
void filterForErrorHandling(ClientHttpRequestFactory requestFactory) {
void filterForErrorHandling(ClientHttpRequestFactory requestFactory) throws IOException {
startServer(requestFactory);
ClientHttpRequestInterceptor interceptor = (request, body, execution) -> {
@ -995,8 +996,8 @@ class RestClientIntegrationTests { @@ -995,8 +996,8 @@ class RestClientIntegrationTests {
RestClient interceptedClient = this.restClient.mutate().requestInterceptor(interceptor).build();
// header not present
prepareResponse(response ->
response.setHeader("Content-Type", "text/plain").setBody("Hello Spring!"));
prepareResponse(builder ->
builder.setHeader("Content-Type", "text/plain").body("Hello Spring!"));
assertThatExceptionOfType(MyException.class).isThrownBy(() ->
interceptedClient.get()
@ -1007,9 +1008,9 @@ class RestClientIntegrationTests { @@ -1007,9 +1008,9 @@ class RestClientIntegrationTests {
// header present
prepareResponse(response -> response.setHeader("Content-Type", "text/plain")
prepareResponse(builder -> builder.setHeader("Content-Type", "text/plain")
.setHeader("Foo", "Bar")
.setBody("Hello Spring!"));
.body("Hello Spring!"));
String result = interceptedClient.get()
.uri("/greeting")
@ -1021,11 +1022,11 @@ class RestClientIntegrationTests { @@ -1021,11 +1022,11 @@ class RestClientIntegrationTests {
}
@ParameterizedRestClientTest
void defaultHeaders(ClientHttpRequestFactory requestFactory) {
void defaultHeaders(ClientHttpRequestFactory requestFactory) throws IOException {
startServer(requestFactory);
prepareResponse(response ->
response.setHeader("Content-Type", "text/plain").setBody("Hello Spring!"));
prepareResponse(builder ->
builder.setHeader("Content-Type", "text/plain").body("Hello Spring!"));
RestClient headersClient = this.restClient.mutate()
.defaultHeaders(headers -> headers.add("foo", "bar"))
@ -1039,15 +1040,15 @@ class RestClientIntegrationTests { @@ -1039,15 +1040,15 @@ class RestClientIntegrationTests {
assertThat(result).isEqualTo("Hello Spring!");
expectRequestCount(1);
expectRequest(request -> assertThat(request.getHeader("foo")).isEqualTo("bar"));
expectRequest(request -> assertThat(request.getHeaders().get("foo")).isEqualTo("bar"));
}
@ParameterizedRestClientTest
void defaultRequest(ClientHttpRequestFactory requestFactory) {
void defaultRequest(ClientHttpRequestFactory requestFactory) throws IOException {
startServer(requestFactory);
prepareResponse(response ->
response.setHeader("Content-Type", "text/plain").setBody("Hello Spring!"));
prepareResponse(builder ->
builder.setHeader("Content-Type", "text/plain").body("Hello Spring!"));
RestClient headersClient = this.restClient.mutate()
.defaultRequest(request -> request.header("foo", "bar"))
@ -1061,15 +1062,15 @@ class RestClientIntegrationTests { @@ -1061,15 +1062,15 @@ class RestClientIntegrationTests {
assertThat(result).isEqualTo("Hello Spring!");
expectRequestCount(1);
expectRequest(request -> assertThat(request.getHeader("foo")).isEqualTo("bar"));
expectRequest(request -> assertThat(request.getHeaders().get("foo")).isEqualTo("bar"));
}
@ParameterizedRestClientTest
void defaultRequestOverride(ClientHttpRequestFactory requestFactory) {
void defaultRequestOverride(ClientHttpRequestFactory requestFactory) throws IOException {
startServer(requestFactory);
prepareResponse(response ->
response.setHeader("Content-Type", "text/plain").setBody("Hello Spring!"));
prepareResponse(builder ->
builder.setHeader("Content-Type", "text/plain").body("Hello Spring!"));
RestClient headersClient = this.restClient.mutate()
.defaultRequest(request -> request.accept(MediaType.APPLICATION_JSON))
@ -1084,15 +1085,15 @@ class RestClientIntegrationTests { @@ -1084,15 +1085,15 @@ class RestClientIntegrationTests {
assertThat(result).isEqualTo("Hello Spring!");
expectRequestCount(1);
expectRequest(request -> assertThat(request.getHeader("Accept")).isEqualTo(MediaType.TEXT_PLAIN_VALUE));
expectRequest(request -> assertThat(request.getHeaders().get("Accept")).isEqualTo(MediaType.TEXT_PLAIN_VALUE));
}
@ParameterizedRestClientTest
void relativeUri(ClientHttpRequestFactory requestFactory) throws URISyntaxException {
void relativeUri(ClientHttpRequestFactory requestFactory) throws URISyntaxException, IOException {
startServer(requestFactory);
prepareResponse(response ->
response.setHeader("Content-Type", "text/plain").setBody("Hello Spring!"));
prepareResponse(builder ->
builder.setHeader("Content-Type", "text/plain").body("Hello Spring!"));
URI uri = new URI(null, null, "/foo bar", null);
@ -1106,15 +1107,15 @@ class RestClientIntegrationTests { @@ -1106,15 +1107,15 @@ class RestClientIntegrationTests {
assertThat(result).isEqualTo("Hello Spring!");
expectRequestCount(1);
expectRequest(request -> assertThat(request.getPath()).isEqualTo("/foo%20bar"));
expectRequest(request -> assertThat(request.getTarget()).isEqualTo("/foo%20bar"));
}
@ParameterizedRestClientTest
void cookieAddsCookie(ClientHttpRequestFactory requestFactory) {
void cookieAddsCookie(ClientHttpRequestFactory requestFactory) throws IOException {
startServer(requestFactory);
prepareResponse(response ->
response.setHeader("Content-Type", "text/plain").setBody("Hello Spring!"));
prepareResponse(builder ->
builder.setHeader("Content-Type", "text/plain").body("Hello Spring!"));
this.restClient.get()
.uri("/greeting")
@ -1124,15 +1125,15 @@ class RestClientIntegrationTests { @@ -1124,15 +1125,15 @@ class RestClientIntegrationTests {
.retrieve()
.body(String.class);
expectRequest(request -> assertThat(request.getHeader("Cookie")).isEqualTo("c1=v1a; c1=v1b; c2=v2a"));
expectRequest(request -> assertThat(request.getHeaders().get("Cookie")).isEqualTo("c1=v1a; c1=v1b; c2=v2a"));
}
@ParameterizedRestClientTest
void cookieOverridesDefaultCookie(ClientHttpRequestFactory requestFactory) {
void cookieOverridesDefaultCookie(ClientHttpRequestFactory requestFactory) throws IOException {
startServer(requestFactory);
prepareResponse(response ->
response.setHeader("Content-Type", "text/plain").setBody("Hello Spring!"));
prepareResponse(builder ->
builder.setHeader("Content-Type", "text/plain").body("Hello Spring!"));
RestClient restClientWithCookies = this.restClient.mutate()
.defaultCookie("testCookie", "firstValue", "secondValue")
@ -1144,15 +1145,15 @@ class RestClientIntegrationTests { @@ -1144,15 +1145,15 @@ class RestClientIntegrationTests {
.retrieve()
.body(String.class);
expectRequest(request -> assertThat(request.getHeader("Cookie")).isEqualTo("testCookie=test"));
expectRequest(request -> assertThat(request.getHeaders().get("Cookie")).isEqualTo("testCookie=test"));
}
@ParameterizedRestClientTest
void cookiesCanRemoveCookie(ClientHttpRequestFactory requestFactory) {
void cookiesCanRemoveCookie(ClientHttpRequestFactory requestFactory) throws IOException {
startServer(requestFactory);
prepareResponse(response ->
response.setHeader("Content-Type", "text/plain").setBody("Hello Spring!"));
prepareResponse(builder ->
builder.setHeader("Content-Type", "text/plain").body("Hello Spring!"));
this.restClient.get()
.uri("/greeting")
@ -1162,13 +1163,12 @@ class RestClientIntegrationTests { @@ -1162,13 +1163,12 @@ class RestClientIntegrationTests {
.retrieve()
.body(String.class);
expectRequest(request -> assertThat(request.getHeader("Cookie")).isEqualTo("test=Hello"));
expectRequest(request -> assertThat(request.getHeaders().get("Cookie")).isEqualTo("test=Hello"));
}
private void prepareResponse(Consumer<MockResponse> consumer) {
MockResponse response = new MockResponse();
consumer.accept(response);
this.server.enqueue(response);
private void prepareResponse(Function<MockResponse.Builder, MockResponse.Builder> f) {
MockResponse.Builder builder = new MockResponse.Builder();
this.server.enqueue(f.apply(builder).build());
}
private void expectRequest(Consumer<RecordedRequest> consumer) {

36
spring-web/src/test/java/org/springframework/web/client/RestClientVersionTests.java

@ -19,9 +19,9 @@ package org.springframework.web.client; @@ -19,9 +19,9 @@ package org.springframework.web.client;
import java.io.IOException;
import java.util.function.Consumer;
import okhttp3.mockwebserver.MockResponse;
import okhttp3.mockwebserver.MockWebServer;
import okhttp3.mockwebserver.RecordedRequest;
import mockwebserver3.MockResponse;
import mockwebserver3.MockWebServer;
import mockwebserver3.RecordedRequest;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
@ -39,46 +39,50 @@ public class RestClientVersionTests { @@ -39,46 +39,50 @@ public class RestClientVersionTests {
private final MockWebServer server = new MockWebServer();
private final RestClient.Builder restClientBuilder = RestClient.builder()
.requestFactory(new JdkClientHttpRequestFactory())
.baseUrl(this.server.url("/").toString());
private RestClient.Builder restClientBuilder;
@BeforeEach
void setUp() {
MockResponse response = new MockResponse();
response.setHeader("Content-Type", "text/plain").setBody("body");
void setUp() throws IOException {
this.server.start();
this.restClientBuilder = RestClient.builder()
.requestFactory(new JdkClientHttpRequestFactory())
.baseUrl(this.server.url("/").toString());
MockResponse response = new MockResponse.Builder()
.setHeader("Content-Type", "text/plain")
.body("body")
.build();
this.server.enqueue(response);
}
@AfterEach
void shutdown() throws IOException {
this.server.shutdown();
void shutdown() {
this.server.close();
}
@Test
void header() {
performRequest(ApiVersionInserter.useHeader("X-API-Version"));
expectRequest(request -> assertThat(request.getHeader("X-API-Version")).isEqualTo("1.2"));
expectRequest(request -> assertThat(request.getHeaders().get("X-API-Version")).isEqualTo("1.2"));
}
@Test
void queryParam() {
performRequest(ApiVersionInserter.useQueryParam("api-version"));
expectRequest(request -> assertThat(request.getPath()).isEqualTo("/path?api-version=1.2"));
expectRequest(request -> assertThat(request.getTarget()).isEqualTo("/path?api-version=1.2"));
}
@Test
void pathSegmentIndexLessThanSize() {
performRequest(ApiVersionInserter.builder().usePathSegment(0).withVersionFormatter(v -> "v" + v).build());
expectRequest(request -> assertThat(request.getPath()).isEqualTo("/v1.2/path"));
expectRequest(request -> assertThat(request.getTarget()).isEqualTo("/v1.2/path"));
}
@Test
void pathSegmentIndexEqualToSize() {
performRequest(ApiVersionInserter.builder().usePathSegment(1).withVersionFormatter(v -> "v" + v).build());
expectRequest(request -> assertThat(request.getPath()).isEqualTo("/path/v1.2"));
expectRequest(request -> assertThat(request.getTarget()).isEqualTo("/path/v1.2"));
}
@Test
@ -94,7 +98,7 @@ public class RestClientVersionTests { @@ -94,7 +98,7 @@ public class RestClientVersionTests {
RestClient restClient = restClientBuilder.defaultApiVersion(1.2).apiVersionInserter(inserter).build();
restClient.get().uri("/path").retrieve().body(String.class);
expectRequest(request -> assertThat(request.getHeader("X-API-Version")).isEqualTo("1.2"));
expectRequest(request -> assertThat(request.getHeaders().get("X-API-Version")).isEqualTo("1.2"));
}
private void performRequest(ApiVersionInserter versionInserter) {

20
spring-web/src/test/java/org/springframework/web/client/RestTemplateTests.java

@ -28,9 +28,9 @@ import java.util.Map; @@ -28,9 +28,9 @@ import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import okhttp3.mockwebserver.MockResponse;
import okhttp3.mockwebserver.MockWebServer;
import okhttp3.mockwebserver.RecordedRequest;
import mockwebserver3.MockResponse;
import mockwebserver3.MockWebServer;
import mockwebserver3.RecordedRequest;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
@ -504,18 +504,18 @@ class RestTemplateTests { @@ -504,18 +504,18 @@ class RestTemplateTests {
@Test // gh-23740
void headerAcceptAllOnPut() throws Exception {
try (MockWebServer server = new MockWebServer()) {
server.enqueue(new MockResponse().setResponseCode(500).setBody("internal server error"));
server.enqueue(new MockResponse.Builder().code(500).body("internal server error").build());
server.start();
template.setRequestFactory(new SimpleClientHttpRequestFactory());
template.put(server.url("/internal/server/error").uri(), null);
assertThat(server.takeRequest().getHeader("Accept")).isEqualTo("*/*");
assertThat(server.takeRequest().getHeaders().get("Accept")).isEqualTo("*/*");
}
}
@Test // gh-23740
void keepGivenAcceptHeaderOnPut() throws Exception {
try (MockWebServer server = new MockWebServer()) {
server.enqueue(new MockResponse().setResponseCode(500).setBody("internal server error"));
server.enqueue(new MockResponse.Builder().code(500).body("internal server error").build());
server.start();
HttpHeaders headers = new HttpHeaders();
headers.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON));
@ -582,11 +582,11 @@ class RestTemplateTests { @@ -582,11 +582,11 @@ class RestTemplateTests {
@Test // gh-23740
void headerAcceptAllOnDelete() throws Exception {
try (MockWebServer server = new MockWebServer()) {
server.enqueue(new MockResponse().setResponseCode(500).setBody("internal server error"));
server.enqueue(new MockResponse.Builder().code(500).body("internal server error").build());
server.start();
template.setRequestFactory(new SimpleClientHttpRequestFactory());
template.delete(server.url("/internal/server/error").uri());
assertThat(server.takeRequest().getHeader("Accept")).isEqualTo("*/*");
assertThat(server.takeRequest().getHeaders().get("Accept")).isEqualTo("*/*");
}
}
@ -773,7 +773,7 @@ class RestTemplateTests { @@ -773,7 +773,7 @@ class RestTemplateTests {
@Test
void requestInterceptorWithBuffering() throws Exception {
try (MockWebServer server = new MockWebServer()) {
server.enqueue(new MockResponse().setResponseCode(200).setBody("Hello Spring!"));
server.enqueue(new MockResponse.Builder().code(200).body("Hello Spring!").build());
server.start();
template.setRequestFactory(new SimpleClientHttpRequestFactory());
template.setInterceptors(List.of((request, body, execution) -> {
@ -793,7 +793,7 @@ class RestTemplateTests { @@ -793,7 +793,7 @@ class RestTemplateTests {
@Test
void buffering() throws Exception {
try (MockWebServer server = new MockWebServer()) {
server.enqueue(new MockResponse().setResponseCode(200).setBody("Hello Spring!"));
server.enqueue(new MockResponse.Builder().code(200).body("Hello Spring!").build());
server.start();
template.setRequestFactory(new SimpleClientHttpRequestFactory());
template.setBufferingPredicate((uri, httpMethod) -> true);

98
spring-web/src/test/java/org/springframework/web/client/support/RestClientAdapterTests.java

@ -28,15 +28,16 @@ import java.util.LinkedHashSet; @@ -28,15 +28,16 @@ import java.util.LinkedHashSet;
import java.util.Optional;
import java.util.Set;
import java.util.function.BiFunction;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.stream.Stream;
import io.micrometer.observation.tck.TestObservationRegistry;
import okhttp3.mockwebserver.MockResponse;
import okhttp3.mockwebserver.MockWebServer;
import okhttp3.mockwebserver.RecordedRequest;
import mockwebserver3.MockResponse;
import mockwebserver3.MockWebServer;
import mockwebserver3.RecordedRequest;
import org.jspecify.annotations.Nullable;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.MethodSource;
@ -82,10 +83,14 @@ class RestClientAdapterTests { @@ -82,10 +83,14 @@ class RestClientAdapterTests {
private final MockWebServer anotherServer = new MockWebServer();
@BeforeEach
void setUp() throws IOException {
this.anotherServer.start();
}
@AfterEach
void shutdown() throws IOException {
this.anotherServer.shutdown();
void shutdown() {
this.anotherServer.close();
}
@ -96,7 +101,7 @@ class RestClientAdapterTests { @@ -96,7 +101,7 @@ class RestClientAdapterTests {
@interface ParameterizedAdapterTest {
}
public static Stream<Object[]> arguments() {
public static Stream<Object[]> arguments() throws IOException {
return Stream.of(
createArgsForAdapter((url, or) -> {
RestClient restClient = RestClient.builder().baseUrl(url).observationRegistry(or).build();
@ -112,12 +117,15 @@ class RestClientAdapterTests { @@ -112,12 +117,15 @@ class RestClientAdapterTests {
@SuppressWarnings("resource")
private static Object[] createArgsForAdapter(
BiFunction<String, TestObservationRegistry, HttpExchangeAdapter> adapterFactory) {
BiFunction<String, TestObservationRegistry, HttpExchangeAdapter> adapterFactory) throws IOException {
MockWebServer server = new MockWebServer();
server.start();
MockResponse response = new MockResponse();
response.setHeader("Content-Type", "text/plain").setBody("Hello Spring!");
MockResponse response = new MockResponse.Builder()
.setHeader("Content-Type", "text/plain")
.body("Hello Spring!")
.build();
server.enqueue(response);
TestObservationRegistry registry = TestObservationRegistry.create();
@ -137,7 +145,7 @@ class RestClientAdapterTests { @@ -137,7 +145,7 @@ class RestClientAdapterTests {
RecordedRequest request = server.takeRequest();
assertThat(response).isEqualTo("Hello Spring!");
assertThat(request.getMethod()).isEqualTo("GET");
assertThat(request.getPath()).isEqualTo("/greeting");
assertThat(request.getTarget()).isEqualTo("/greeting");
assertThat(registry).hasObservationWithNameEqualTo("http.client.requests").that()
.hasLowCardinalityKeyValue("uri", "/greeting");
}
@ -151,7 +159,7 @@ class RestClientAdapterTests { @@ -151,7 +159,7 @@ class RestClientAdapterTests {
assertThat(response.getStatusCode()).isEqualTo(HttpStatus.OK);
assertThat(response.getBody()).isEqualTo("Hello Spring!");
assertThat(request.getMethod()).isEqualTo("GET");
assertThat(request.getPath()).isEqualTo("/greeting/456");
assertThat(request.getTarget()).isEqualTo("/greeting/456");
assertThat(registry).hasObservationWithNameEqualTo("http.client.requests").that()
.hasLowCardinalityKeyValue("uri", "/greeting/{id}");
}
@ -165,15 +173,15 @@ class RestClientAdapterTests { @@ -165,15 +173,15 @@ class RestClientAdapterTests {
RecordedRequest request = server.takeRequest();
assertThat(response.orElse("empty")).isEqualTo("Hello Spring!");
assertThat(request.getMethod()).isEqualTo("GET");
assertThat(request.getRequestUrl().uri()).isEqualTo(dynamicUri);
assertThat(request.getUrl().uri()).isEqualTo(dynamicUri);
assertThat(registry).hasObservationWithNameEqualTo("http.client.requests").that()
.hasLowCardinalityKeyValue("uri", "none");
}
@Test
void greetingWithApiVersion() throws Exception {
prepareResponse(response ->
response.setHeader("Content-Type", "text/plain").setBody("Hello Spring 2!"));
prepareResponse(builder ->
builder.setHeader("Content-Type", "text/plain").body("Hello Spring 2!"));
RestClient restClient = RestClient.builder()
.baseUrl(anotherServer.url("/").toString())
@ -186,14 +194,14 @@ class RestClientAdapterTests { @@ -186,14 +194,14 @@ class RestClientAdapterTests {
String actualResponse = service.getGreetingWithVersion();
RecordedRequest request = anotherServer.takeRequest();
assertThat(request.getHeader("X-API-Version")).isEqualTo("1.2");
assertThat(request.getHeaders().get("X-API-Version")).isEqualTo("1.2");
assertThat(actualResponse).isEqualTo("Hello Spring 2!");
}
@ParameterizedAdapterTest
void getWithUriBuilderFactory(MockWebServer server, Service service) throws InterruptedException {
prepareResponse(response ->
response.setHeader("Content-Type", "text/plain").setBody("Hello Spring 2!"));
prepareResponse(builder ->
builder.setHeader("Content-Type", "text/plain").body("Hello Spring 2!"));
String url = this.anotherServer.url("/").toString();
UriBuilderFactory factory = new DefaultUriBuilderFactory(url);
@ -204,14 +212,14 @@ class RestClientAdapterTests { @@ -204,14 +212,14 @@ class RestClientAdapterTests {
assertThat(actualResponse.getStatusCode()).isEqualTo(HttpStatus.OK);
assertThat(actualResponse.getBody()).isEqualTo("Hello Spring 2!");
assertThat(request.getMethod()).isEqualTo("GET");
assertThat(request.getPath()).isEqualTo("/greeting");
assertThat(request.getTarget()).isEqualTo("/greeting");
assertThat(server.getRequestCount()).isEqualTo(0);
}
@ParameterizedAdapterTest
void getWithFactoryPathVariableAndRequestParam(MockWebServer server, Service service) throws InterruptedException {
prepareResponse(response ->
response.setHeader("Content-Type", "text/plain").setBody("Hello Spring 2!"));
prepareResponse(builder ->
builder.setHeader("Content-Type", "text/plain").body("Hello Spring 2!"));
String url = this.anotherServer.url("/").toString();
UriBuilderFactory factory = new DefaultUriBuilderFactory(url);
@ -222,14 +230,14 @@ class RestClientAdapterTests { @@ -222,14 +230,14 @@ class RestClientAdapterTests {
assertThat(actualResponse.getStatusCode()).isEqualTo(HttpStatus.OK);
assertThat(actualResponse.getBody()).isEqualTo("Hello Spring 2!");
assertThat(request.getMethod()).isEqualTo("GET");
assertThat(request.getPath()).isEqualTo("/greeting/123?param=test");
assertThat(request.getTarget()).isEqualTo("/greeting/123?param=test");
assertThat(server.getRequestCount()).isEqualTo(0);
}
@ParameterizedAdapterTest
void getWithIgnoredUriBuilderFactory(MockWebServer server, Service service) throws InterruptedException {
prepareResponse(response ->
response.setHeader("Content-Type", "text/plain").setBody("Hello Spring 2!"));
prepareResponse(builder ->
builder.setHeader("Content-Type", "text/plain").body("Hello Spring 2!"));
URI dynamicUri = server.url("/greeting/123").uri();
UriBuilderFactory factory = new DefaultUriBuilderFactory(this.anotherServer.url("/").toString());
@ -240,7 +248,7 @@ class RestClientAdapterTests { @@ -240,7 +248,7 @@ class RestClientAdapterTests {
assertThat(actualResponse.getStatusCode()).isEqualTo(HttpStatus.OK);
assertThat(actualResponse.getBody()).isEqualTo("Hello Spring!");
assertThat(request.getMethod()).isEqualTo("GET");
assertThat(request.getPath()).isEqualTo("/greeting/123");
assertThat(request.getTarget()).isEqualTo("/greeting/123");
assertThat(this.anotherServer.getRequestCount()).isEqualTo(0);
}
@ -250,9 +258,9 @@ class RestClientAdapterTests { @@ -250,9 +258,9 @@ class RestClientAdapterTests {
RecordedRequest request = server.takeRequest();
assertThat(request.getMethod()).isEqualTo("POST");
assertThat(request.getPath()).isEqualTo("/greeting");
assertThat(request.getTarget()).isEqualTo("/greeting");
assertThat(request.getHeaders().get("testHeaderName")).isEqualTo("testHeader");
assertThat(request.getBody().readUtf8()).isEqualTo("testBody");
assertThat(request.getBody().utf8()).isEqualTo("testBody");
}
@ParameterizedAdapterTest
@ -265,7 +273,7 @@ class RestClientAdapterTests { @@ -265,7 +273,7 @@ class RestClientAdapterTests {
RecordedRequest request = server.takeRequest();
assertThat(request.getHeaders().get("Content-Type")).isEqualTo("application/x-www-form-urlencoded");
assertThat(request.getBody().readUtf8()).isEqualTo("param1=value+1&param2=value+2");
assertThat(request.getBody().utf8()).isEqualTo("param1=value+1&param2=value+2");
}
@ParameterizedAdapterTest // gh-30342
@ -277,7 +285,7 @@ class RestClientAdapterTests { @@ -277,7 +285,7 @@ class RestClientAdapterTests {
RecordedRequest request = server.takeRequest();
assertThat(request.getHeaders().get("Content-Type")).startsWith("multipart/form-data;boundary=");
assertThat(request.getBody().readUtf8()).containsSubsequence(
assertThat(request.getBody().utf8()).containsSubsequence(
"Content-Disposition: form-data; name=\"file\"; filename=\"originalTestFileName\"",
"Content-Type: application/json", "Content-Length: 4", "test",
"Content-Disposition: form-data; name=\"anotherPart\"", "Content-Type: text/plain;charset=UTF-8",
@ -293,8 +301,8 @@ class RestClientAdapterTests { @@ -293,8 +301,8 @@ class RestClientAdapterTests {
RecordedRequest request = server.takeRequest();
assertThat(request.getMethod()).isEqualTo("POST");
assertThat(request.getPath()).isEqualTo("/persons");
assertThat(request.getBody().readUtf8()).isEqualTo("[{\"name\":\"John\"},{\"name\":\"Richard\"}]");
assertThat(request.getTarget()).isEqualTo("/persons");
assertThat(request.getBody().utf8()).isEqualTo("[{\"name\":\"John\"},{\"name\":\"Richard\"}]");
}
@ParameterizedAdapterTest
@ -303,7 +311,7 @@ class RestClientAdapterTests { @@ -303,7 +311,7 @@ class RestClientAdapterTests {
RecordedRequest request = server.takeRequest();
assertThat(request.getMethod()).isEqualTo("PUT");
assertThat(request.getHeader("Cookie")).isEqualTo("firstCookie=test1; secondCookie=test2");
assertThat(request.getHeaders().get("Cookie")).isEqualTo("firstCookie=test1; secondCookie=test2");
}
@ParameterizedAdapterTest
@ -312,38 +320,37 @@ class RestClientAdapterTests { @@ -312,38 +320,37 @@ class RestClientAdapterTests {
RecordedRequest request = server.takeRequest();
assertThat(request.getMethod()).isEqualTo("PUT");
assertThat(request.getHeader("Cookie")).isEqualTo("testCookie=test1; testCookie=test2");
assertThat(request.getHeaders().get("Cookie")).isEqualTo("testCookie=test1; testCookie=test2");
}
@Test
void getInputStream() throws Exception {
prepareResponse(response ->
response.setHeader("Content-Type", "text/plain").setBody("Hello Spring 2!"));
prepareResponse(builder ->
builder.setHeader("Content-Type", "text/plain").body("Hello Spring 2!"));
InputStream inputStream = initService().getInputStream();
RecordedRequest request = this.anotherServer.takeRequest();
assertThat(request.getPath()).isEqualTo("/input-stream");
assertThat(request.getTarget()).isEqualTo("/input-stream");
assertThat(StreamUtils.copyToString(inputStream, StandardCharsets.UTF_8)).isEqualTo("Hello Spring 2!");
}
@Test
void postOutputStream() throws Exception {
prepareResponse(response ->
response.setHeader("Content-Type", "text/plain").setBody("Hello Spring 2!"));
prepareResponse(builder ->
builder.setHeader("Content-Type", "text/plain").body("Hello Spring 2!"));
String body = "test stream";
initService().postOutputStream(outputStream -> outputStream.write(body.getBytes()));
RecordedRequest request = this.anotherServer.takeRequest();
assertThat(request.getPath()).isEqualTo("/output-stream");
assertThat(request.getBody().readUtf8()).isEqualTo(body);
assertThat(request.getTarget()).isEqualTo("/output-stream");
assertThat(request.getBody().utf8()).isEqualTo(body);
}
@Test
void handleNotFoundException() {
MockResponse response = new MockResponse();
response.setResponseCode(404);
MockResponse response = new MockResponse.Builder().code(404).build();
this.anotherServer.enqueue(response);
RestClientAdapter clientAdapter = RestClientAdapter.create(
@ -366,10 +373,9 @@ class RestClientAdapterTests { @@ -366,10 +373,9 @@ class RestClientAdapterTests {
return HttpServiceProxyFactory.builderFor(adapter).build().createClient(Service.class);
}
private void prepareResponse(Consumer<MockResponse> consumer) {
MockResponse response = new MockResponse();
consumer.accept(response);
this.anotherServer.enqueue(response);
private void prepareResponse(Function<MockResponse.Builder, MockResponse.Builder> f) {
MockResponse.Builder builder = new MockResponse.Builder();
this.anotherServer.enqueue(f.apply(builder).build());
}

22
spring-web/src/test/java/org/springframework/web/client/support/RestClientProxyRegistryIntegrationTests.java

@ -16,11 +16,9 @@ @@ -16,11 +16,9 @@
package org.springframework.web.client.support;
import java.io.IOException;
import okhttp3.mockwebserver.MockResponse;
import okhttp3.mockwebserver.MockWebServer;
import okhttp3.mockwebserver.RecordedRequest;
import mockwebserver3.MockResponse;
import mockwebserver3.MockWebServer;
import mockwebserver3.RecordedRequest;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
@ -61,8 +59,8 @@ public class RestClientProxyRegistryIntegrationTests { @@ -61,8 +59,8 @@ public class RestClientProxyRegistryIntegrationTests {
}
@AfterEach
void shutdown() throws IOException {
this.server.shutdown();
void shutdown() {
this.server.close();
}
@ -89,7 +87,7 @@ public class RestClientProxyRegistryIntegrationTests { @@ -89,7 +87,7 @@ public class RestClientProxyRegistryIntegrationTests {
assertThat(registry.getClient(GreetingB.class)).isSameAs(greetingB);
for (int i = 0; i < 4; i++) {
this.server.enqueue(new MockResponse().setBody("body"));
this.server.enqueue(new MockResponse.Builder().body("body").build());
}
echoA.handle("a");
@ -97,22 +95,22 @@ public class RestClientProxyRegistryIntegrationTests { @@ -97,22 +95,22 @@ public class RestClientProxyRegistryIntegrationTests {
RecordedRequest request = this.server.takeRequest();
assertThat(request.getMethod()).isEqualTo("GET");
assertThat(request.getPath()).isEqualTo("/echoA?input=a");
assertThat(request.getTarget()).isEqualTo("/echoA?input=a");
request = this.server.takeRequest();
assertThat(request.getMethod()).isEqualTo("GET");
assertThat(request.getPath()).isEqualTo("/echoB?input=b");
assertThat(request.getTarget()).isEqualTo("/echoB?input=b");
greetingA.handle("a");
greetingB.handle("b");
request = this.server.takeRequest();
assertThat(request.getMethod()).isEqualTo("GET");
assertThat(request.getPath()).isEqualTo("/greetingA?input=a");
assertThat(request.getTarget()).isEqualTo("/greetingA?input=a");
request = this.server.takeRequest();
assertThat(request.getMethod()).isEqualTo("GET");
assertThat(request.getPath()).isEqualTo("/greetingB?input=b");
assertThat(request.getTarget()).isEqualTo("/greetingB?input=b");
}
@Test

48
spring-web/src/test/kotlin/org/springframework/web/client/support/KotlinRestTemplateHttpServiceProxyTests.kt

@ -16,8 +16,8 @@ @@ -16,8 +16,8 @@
package org.springframework.web.client.support
import okhttp3.mockwebserver.MockResponse
import okhttp3.mockwebserver.MockWebServer
import mockwebserver3.MockResponse
import mockwebserver3.MockWebServer
import org.assertj.core.api.Assertions.assertThat
import org.junit.jupiter.api.AfterEach
import org.junit.jupiter.api.BeforeEach
@ -57,8 +57,10 @@ class KotlinRestTemplateHttpServiceProxyTests { @@ -57,8 +57,10 @@ class KotlinRestTemplateHttpServiceProxyTests {
@BeforeEach
fun setUp() {
server = MockWebServer()
server.start()
prepareResponse()
anotherServer = anotherServer()
anotherServer.start()
testService = initTestService()
}
@ -73,8 +75,8 @@ class KotlinRestTemplateHttpServiceProxyTests { @@ -73,8 +75,8 @@ class KotlinRestTemplateHttpServiceProxyTests {
@AfterEach
fun shutDown() {
server.shutdown()
anotherServer.shutdown()
server.close()
anotherServer.close()
}
@Test
@ -85,7 +87,7 @@ class KotlinRestTemplateHttpServiceProxyTests { @@ -85,7 +87,7 @@ class KotlinRestTemplateHttpServiceProxyTests {
val request = server.takeRequest()
assertThat(response).isEqualTo("Hello Spring!")
assertThat(request.method).isEqualTo("GET")
assertThat(request.path).isEqualTo("/test")
assertThat(request.target).isEqualTo("/test")
}
@Test
@ -97,20 +99,20 @@ class KotlinRestTemplateHttpServiceProxyTests { @@ -97,20 +99,20 @@ class KotlinRestTemplateHttpServiceProxyTests {
assertThat(response.statusCode).isEqualTo(HttpStatus.OK)
assertThat(response.body).isEqualTo("Hello Spring!")
assertThat(request.method).isEqualTo("GET")
assertThat(request.path).isEqualTo("/test/456")
assertThat(request.target).isEqualTo("/test/456")
}
@Test
@Throws(InterruptedException::class)
fun getRequestWithDynamicUri() {
val dynamicUri = server.url("/greeting/123").uri()
val dynamicUri = server.url("/greeting/123").toUri()
val response = testService.getRequestWithDynamicUri(dynamicUri, "456")
val request = server.takeRequest()
assertThat(response.orElse("empty")).isEqualTo("Hello Spring!")
assertThat(request.method).isEqualTo("GET")
assertThat(request.requestUrl.uri()).isEqualTo(dynamicUri)
assertThat(request.url.toUri()).isEqualTo(dynamicUri)
}
@Test
@ -120,9 +122,9 @@ class KotlinRestTemplateHttpServiceProxyTests { @@ -120,9 +122,9 @@ class KotlinRestTemplateHttpServiceProxyTests {
val request = server.takeRequest()
assertThat(request.method).isEqualTo("POST")
assertThat(request.path).isEqualTo("/test")
assertThat(request.target).isEqualTo("/test")
assertThat(request.headers["testHeaderName"]).isEqualTo("testHeader")
assertThat(request.body.readUtf8()).isEqualTo("testBody")
assertThat(request.body!!.utf8()).isEqualTo("testBody")
}
@Test
@ -136,7 +138,7 @@ class KotlinRestTemplateHttpServiceProxyTests { @@ -136,7 +138,7 @@ class KotlinRestTemplateHttpServiceProxyTests {
val request = server.takeRequest()
assertThat(request.headers["Content-Type"]).isEqualTo("application/x-www-form-urlencoded")
assertThat(request.body.readUtf8()).isEqualTo("param1=value+1&param2=value+2")
assertThat(request.body!!.utf8()).isEqualTo("param1=value+1&param2=value+2")
}
// gh-30342
@ -152,7 +154,7 @@ class KotlinRestTemplateHttpServiceProxyTests { @@ -152,7 +154,7 @@ class KotlinRestTemplateHttpServiceProxyTests {
val request = server.takeRequest()
assertThat(request.headers["Content-Type"]).startsWith("multipart/form-data;boundary=")
assertThat(request.body.readUtf8()).containsSubsequence(
assertThat(request.body!!.utf8()).containsSubsequence(
"Content-Disposition: form-data; name=\"file\"; filename=\"originalTestFileName\"",
"Content-Type: application/json", "Content-Length: 4", "test",
"Content-Disposition: form-data; name=\"anotherPart\"", "Content-Type: text/plain;charset=UTF-8",
@ -166,7 +168,7 @@ class KotlinRestTemplateHttpServiceProxyTests { @@ -166,7 +168,7 @@ class KotlinRestTemplateHttpServiceProxyTests {
val request = server.takeRequest()
assertThat(request.method).isEqualTo("PUT")
assertThat(request.getHeader("Cookie"))
assertThat(request.headers["Cookie"])
.isEqualTo("firstCookie=test1; secondCookie=test2")
}
@ -177,7 +179,7 @@ class KotlinRestTemplateHttpServiceProxyTests { @@ -177,7 +179,7 @@ class KotlinRestTemplateHttpServiceProxyTests {
val request = server.takeRequest()
assertThat(request.method).isEqualTo("PUT")
assertThat(request.getHeader("Cookie"))
assertThat(request.headers["Cookie"])
.isEqualTo("testCookie=test1; testCookie=test2")
}
@ -194,7 +196,7 @@ class KotlinRestTemplateHttpServiceProxyTests { @@ -194,7 +196,7 @@ class KotlinRestTemplateHttpServiceProxyTests {
assertThat(actualResponse.statusCode).isEqualTo(HttpStatus.OK)
assertThat(actualResponse.body).isEqualTo("Hello Spring 2!")
assertThat(request.method).isEqualTo("GET")
assertThat(request.path).isEqualTo("/greeting")
assertThat(request.target).isEqualTo("/greeting")
assertThat(server.requestCount).isEqualTo(0)
}
@ -212,14 +214,14 @@ class KotlinRestTemplateHttpServiceProxyTests { @@ -212,14 +214,14 @@ class KotlinRestTemplateHttpServiceProxyTests {
assertThat(actualResponse.statusCode).isEqualTo(HttpStatus.OK)
assertThat(actualResponse.body).isEqualTo("Hello Spring 2!")
assertThat(request.method).isEqualTo("GET")
assertThat(request.path).isEqualTo("/greeting/123?param=test")
assertThat(request.target).isEqualTo("/greeting/123?param=test")
assertThat(server.requestCount).isEqualTo(0)
}
@Test
@Throws(InterruptedException::class)
fun getWithIgnoredUriBuilderFactory() {
val dynamicUri = server.url("/greeting/123").uri()
val dynamicUri = server.url("/greeting/123").toUri()
val factory: UriBuilderFactory = DefaultUriBuilderFactory(anotherServer.url("/")
.toString())
@ -230,21 +232,23 @@ class KotlinRestTemplateHttpServiceProxyTests { @@ -230,21 +232,23 @@ class KotlinRestTemplateHttpServiceProxyTests {
assertThat(actualResponse.statusCode).isEqualTo(HttpStatus.OK)
assertThat(actualResponse.body).isEqualTo("Hello Spring!")
assertThat(request.method).isEqualTo("GET")
assertThat(request.path).isEqualTo("/greeting/123")
assertThat(request.target).isEqualTo("/greeting/123")
assertThat(anotherServer.requestCount).isEqualTo(0)
}
private fun prepareResponse() {
val response = MockResponse()
response.setHeader("Content-Type", "text/plain").setBody("Hello Spring!")
val response = MockResponse.Builder()
.setHeader("Content-Type", "text/plain").body("Hello Spring!").build()
server.enqueue(response)
}
private fun anotherServer(): MockWebServer {
val anotherServer = MockWebServer()
val response = MockResponse()
response.setHeader("Content-Type", "text/plain").setBody("Hello Spring 2!")
val response = MockResponse.Builder()
.setHeader("Content-Type", "text/plain")
.body("Hello Spring 2!")
.build()
anotherServer.enqueue(response)
return anotherServer
}

2
spring-webflux/spring-webflux.gradle

@ -40,7 +40,7 @@ dependencies { @@ -40,7 +40,7 @@ dependencies {
testImplementation(testFixtures(project(":spring-core")))
testImplementation(testFixtures(project(":spring-web")))
testImplementation("com.fasterxml:aalto-xml")
testImplementation("com.squareup.okhttp3:mockwebserver")
testImplementation("com.squareup.okhttp3:mockwebserver3")
testImplementation("io.micrometer:context-propagation")
testImplementation("io.micrometer:micrometer-observation-test")
testImplementation("io.projectreactor:reactor-test")

61
spring-webflux/src/test/java/org/springframework/web/reactive/function/client/WebClientDataBufferAllocatingTests.java

@ -16,6 +16,7 @@ @@ -16,6 +16,7 @@
package org.springframework.web.reactive.function.client;
import java.io.IOException;
import java.time.Duration;
import java.util.Collections;
import java.util.Map;
@ -23,8 +24,8 @@ import java.util.function.Function; @@ -23,8 +24,8 @@ import java.util.function.Function;
import io.netty.buffer.ByteBufAllocator;
import io.netty.channel.ChannelOption;
import okhttp3.mockwebserver.MockResponse;
import okhttp3.mockwebserver.MockWebServer;
import mockwebserver3.MockResponse;
import mockwebserver3.MockWebServer;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.TestInstance;
@ -71,9 +72,10 @@ class WebClientDataBufferAllocatingTests extends AbstractDataBufferAllocatingTes @@ -71,9 +72,10 @@ class WebClientDataBufferAllocatingTests extends AbstractDataBufferAllocatingTes
this.factory.destroy();
}
private void setUp(DataBufferFactory bufferFactory) {
private void setUp(DataBufferFactory bufferFactory) throws IOException {
super.bufferFactory = bufferFactory;
this.server = new MockWebServer();
this.server.start();
this.webClient = WebClient
.builder()
.clientConnector(initConnector())
@ -96,13 +98,14 @@ class WebClientDataBufferAllocatingTests extends AbstractDataBufferAllocatingTes @@ -96,13 +98,14 @@ class WebClientDataBufferAllocatingTests extends AbstractDataBufferAllocatingTes
@ParameterizedDataBufferAllocatingTest
void bodyToMonoVoid(DataBufferFactory bufferFactory) {
void bodyToMonoVoid(DataBufferFactory bufferFactory) throws IOException {
setUp(bufferFactory);
this.server.enqueue(new MockResponse()
.setResponseCode(201)
this.server.enqueue(new MockResponse.Builder().
code(201)
.setHeader("Content-Type", "application/json")
.setChunkedBody("{\"foo\" : {\"bar\" : \"123\", \"baz\" : \"456\"}}", 5));
.chunkedBody("{\"foo\" : {\"bar\" : \"123\", \"baz\" : \"456\"}}", 5)
.build());
Mono<Void> mono = this.webClient.get()
.uri("/json").accept(MediaType.APPLICATION_JSON)
@ -114,12 +117,13 @@ class WebClientDataBufferAllocatingTests extends AbstractDataBufferAllocatingTes @@ -114,12 +117,13 @@ class WebClientDataBufferAllocatingTests extends AbstractDataBufferAllocatingTes
}
@ParameterizedDataBufferAllocatingTest // SPR-17482
void bodyToMonoVoidWithoutContentType(DataBufferFactory bufferFactory) {
void bodyToMonoVoidWithoutContentType(DataBufferFactory bufferFactory) throws IOException {
setUp(bufferFactory);
this.server.enqueue(new MockResponse()
.setResponseCode(HttpStatus.ACCEPTED.value())
.setChunkedBody("{\"foo\" : \"123\", \"baz\" : \"456\", \"baz\" : \"456\"}", 5));
this.server.enqueue(new MockResponse.Builder()
.code(HttpStatus.ACCEPTED.value())
.chunkedBody("{\"foo\" : \"123\", \"baz\" : \"456\", \"baz\" : \"456\"}", 5)
.build());
Mono<Map<String, String>> mono = this.webClient.get()
.uri("/sample").accept(MediaType.APPLICATION_JSON)
@ -131,7 +135,7 @@ class WebClientDataBufferAllocatingTests extends AbstractDataBufferAllocatingTes @@ -131,7 +135,7 @@ class WebClientDataBufferAllocatingTests extends AbstractDataBufferAllocatingTes
}
@ParameterizedDataBufferAllocatingTest
void onStatusWithBodyNotConsumed(DataBufferFactory bufferFactory) {
void onStatusWithBodyNotConsumed(DataBufferFactory bufferFactory) throws IOException {
setUp(bufferFactory);
RuntimeException ex = new RuntimeException("response error");
@ -139,7 +143,7 @@ class WebClientDataBufferAllocatingTests extends AbstractDataBufferAllocatingTes @@ -139,7 +143,7 @@ class WebClientDataBufferAllocatingTests extends AbstractDataBufferAllocatingTes
}
@ParameterizedDataBufferAllocatingTest
void onStatusWithBodyConsumed(DataBufferFactory bufferFactory) {
void onStatusWithBodyConsumed(DataBufferFactory bufferFactory) throws IOException {
setUp(bufferFactory);
RuntimeException ex = new RuntimeException("response error");
@ -147,7 +151,7 @@ class WebClientDataBufferAllocatingTests extends AbstractDataBufferAllocatingTes @@ -147,7 +151,7 @@ class WebClientDataBufferAllocatingTests extends AbstractDataBufferAllocatingTes
}
@ParameterizedDataBufferAllocatingTest // SPR-17473
void onStatusWithMonoErrorAndBodyNotConsumed(DataBufferFactory bufferFactory) {
void onStatusWithMonoErrorAndBodyNotConsumed(DataBufferFactory bufferFactory) throws IOException {
setUp(bufferFactory);
RuntimeException ex = new RuntimeException("response error");
@ -155,7 +159,7 @@ class WebClientDataBufferAllocatingTests extends AbstractDataBufferAllocatingTes @@ -155,7 +159,7 @@ class WebClientDataBufferAllocatingTests extends AbstractDataBufferAllocatingTes
}
@ParameterizedDataBufferAllocatingTest
void onStatusWithMonoErrorAndBodyConsumed(DataBufferFactory bufferFactory) {
void onStatusWithMonoErrorAndBodyConsumed(DataBufferFactory bufferFactory) throws IOException {
setUp(bufferFactory);
RuntimeException ex = new RuntimeException("response error");
@ -163,7 +167,7 @@ class WebClientDataBufferAllocatingTests extends AbstractDataBufferAllocatingTes @@ -163,7 +167,7 @@ class WebClientDataBufferAllocatingTests extends AbstractDataBufferAllocatingTes
}
@ParameterizedDataBufferAllocatingTest // gh-23230
void onStatusWithImmediateErrorAndBodyNotConsumed(DataBufferFactory bufferFactory) {
void onStatusWithImmediateErrorAndBodyNotConsumed(DataBufferFactory bufferFactory) throws IOException {
setUp(bufferFactory);
RuntimeException ex = new RuntimeException("response error");
@ -173,13 +177,14 @@ class WebClientDataBufferAllocatingTests extends AbstractDataBufferAllocatingTes @@ -173,13 +177,14 @@ class WebClientDataBufferAllocatingTests extends AbstractDataBufferAllocatingTes
}
@ParameterizedDataBufferAllocatingTest
void releaseBody(DataBufferFactory bufferFactory) {
void releaseBody(DataBufferFactory bufferFactory) throws IOException {
setUp(bufferFactory);
this.server.enqueue(new MockResponse()
.setResponseCode(200)
this.server.enqueue(new MockResponse.Builder()
.code(200)
.setHeader("Content-Type", "text/plain")
.setBody("foo bar"));
.body("foo bar")
.build());
Mono<Void> result = this.webClient.get()
.exchangeToMono(ClientResponse::releaseBody);
@ -190,13 +195,14 @@ class WebClientDataBufferAllocatingTests extends AbstractDataBufferAllocatingTes @@ -190,13 +195,14 @@ class WebClientDataBufferAllocatingTests extends AbstractDataBufferAllocatingTes
}
@ParameterizedDataBufferAllocatingTest
void exchangeToBodilessEntity(DataBufferFactory bufferFactory) {
void exchangeToBodilessEntity(DataBufferFactory bufferFactory) throws IOException {
setUp(bufferFactory);
this.server.enqueue(new MockResponse()
.setResponseCode(201)
this.server.enqueue(new MockResponse.Builder()
.code(201)
.setHeader("Foo", "bar")
.setBody("foo bar"));
.body("foo bar")
.build());
Mono<ResponseEntity<Void>> result = this.webClient.get()
.exchangeToMono(ClientResponse::toBodilessEntity);
@ -217,10 +223,11 @@ class WebClientDataBufferAllocatingTests extends AbstractDataBufferAllocatingTes @@ -217,10 +223,11 @@ class WebClientDataBufferAllocatingTests extends AbstractDataBufferAllocatingTes
HttpStatus errorStatus = HttpStatus.BAD_GATEWAY;
this.server.enqueue(new MockResponse()
.setResponseCode(errorStatus.value())
this.server.enqueue(new MockResponse.Builder()
.code(errorStatus.value())
.setHeader("Content-Type", "application/json")
.setChunkedBody("{\"error\" : {\"status\" : 502, \"message\" : \"Bad gateway.\"}}", 5));
.chunkedBody("{\"error\" : {\"status\" : 502, \"message\" : \"Bad gateway.\"}}", 5)
.build());
Mono<String> mono = this.webClient.get()
.uri("/json").accept(MediaType.APPLICATION_JSON)

433
spring-webflux/src/test/java/org/springframework/web/reactive/function/client/WebClientIntegrationTests.java

@ -16,7 +16,6 @@ @@ -16,7 +16,6 @@
package org.springframework.web.reactive.function.client;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
@ -41,9 +40,9 @@ import java.util.stream.Collectors; @@ -41,9 +40,9 @@ import java.util.stream.Collectors;
import java.util.stream.Stream;
import io.netty.util.Attribute;
import okhttp3.mockwebserver.MockResponse;
import okhttp3.mockwebserver.MockWebServer;
import okhttp3.mockwebserver.RecordedRequest;
import mockwebserver3.MockResponse;
import mockwebserver3.MockWebServer;
import mockwebserver3.RecordedRequest;
import org.eclipse.jetty.client.Request;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Test;
@ -118,8 +117,9 @@ class WebClientIntegrationTests { @@ -118,8 +117,9 @@ class WebClientIntegrationTests {
private WebClient webClient;
private void startServer(ClientHttpConnector connector) {
private void startServer(ClientHttpConnector connector) throws IOException {
this.server = new MockWebServer();
this.server.start();
this.webClient = WebClient
.builder()
.clientConnector(connector)
@ -128,19 +128,20 @@ class WebClientIntegrationTests { @@ -128,19 +128,20 @@ class WebClientIntegrationTests {
}
@AfterEach
void shutdown() throws IOException {
void shutdown() {
if (server != null) {
this.server.shutdown();
this.server.close();
}
}
@ParameterizedWebClientTest
void retrieve(ClientHttpConnector connector) {
void retrieve(ClientHttpConnector connector) throws IOException {
startServer(connector);
prepareResponse(response ->
response.setHeader("Content-Type", "text/plain").setBody("Hello Spring!"));
prepareResponse(builder -> builder
.setHeader("Content-Type", "text/plain")
.body("Hello Spring!"));
Mono<String> result = this.webClient.get()
.uri("/greeting")
@ -156,20 +157,20 @@ class WebClientIntegrationTests { @@ -156,20 +157,20 @@ class WebClientIntegrationTests {
expectRequestCount(1);
expectRequest(request -> {
assertThat(request.getHeader(HttpHeaders.COOKIE)).isEqualTo("testkey=testvalue");
assertThat(request.getHeader("X-Test-Header")).isEqualTo("testvalue");
assertThat(request.getHeader(HttpHeaders.ACCEPT)).isEqualTo("*/*");
assertThat(request.getPath()).isEqualTo("/greeting");
assertThat(request.getHeaders().get(HttpHeaders.COOKIE)).isEqualTo("testkey=testvalue");
assertThat(request.getHeaders().get("X-Test-Header")).isEqualTo("testvalue");
assertThat(request.getHeaders().get(HttpHeaders.ACCEPT)).isEqualTo("*/*");
assertThat(request.getTarget()).isEqualTo("/greeting");
});
}
@ParameterizedWebClientTest
void retrieveJson(ClientHttpConnector connector) {
void retrieveJson(ClientHttpConnector connector) throws IOException {
startServer(connector);
prepareResponse(response -> response
prepareResponse(builder -> builder
.setHeader("Content-Type", "application/json")
.setBody("{\"bar\":\"barbar\",\"foo\":\"foofoo\"}"));
.body("{\"bar\":\"barbar\",\"foo\":\"foofoo\"}"));
Mono<Pojo> result = this.webClient.get()
.uri("/pojo")
@ -184,15 +185,15 @@ class WebClientIntegrationTests { @@ -184,15 +185,15 @@ class WebClientIntegrationTests {
expectRequestCount(1);
expectRequest(request -> {
assertThat(request.getPath()).isEqualTo("/pojo");
assertThat(request.getHeader(HttpHeaders.ACCEPT)).isEqualTo("application/json");
assertThat(request.getTarget()).isEqualTo("/pojo");
assertThat(request.getHeaders().get(HttpHeaders.ACCEPT)).isEqualTo("application/json");
});
}
@ParameterizedWebClientTest
void applyAttributesToNativeRequest(ClientHttpConnector connector) {
void applyAttributesToNativeRequest(ClientHttpConnector connector) throws IOException {
startServer(connector);
prepareResponse(response -> {});
prepareResponse(Function.identity());
final AtomicReference<Object> nativeRequest = new AtomicReference<>();
Mono<Void> result = this.webClient.get()
@ -227,12 +228,13 @@ class WebClientIntegrationTests { @@ -227,12 +228,13 @@ class WebClientIntegrationTests {
@ParameterizedWebClientTest
void retrieveJsonWithParameterizedTypeReference(ClientHttpConnector connector) {
void retrieveJsonWithParameterizedTypeReference(ClientHttpConnector connector) throws IOException {
startServer(connector);
String content = "{\"containerValue\":{\"bar\":\"barbar\",\"foo\":\"foofoo\"}}";
prepareResponse(response -> response
.setHeader("Content-Type", "application/json").setBody(content));
prepareResponse(builder -> builder
.setHeader("Content-Type", "application/json")
.body(content));
Mono<ValueContainer<Pojo>> result = this.webClient.get()
.uri("/json").accept(MediaType.APPLICATION_JSON)
@ -245,18 +247,19 @@ class WebClientIntegrationTests { @@ -245,18 +247,19 @@ class WebClientIntegrationTests {
expectRequestCount(1);
expectRequest(request -> {
assertThat(request.getPath()).isEqualTo("/json");
assertThat(request.getHeader(HttpHeaders.ACCEPT)).isEqualTo("application/json");
assertThat(request.getTarget()).isEqualTo("/json");
assertThat(request.getHeaders().get(HttpHeaders.ACCEPT)).isEqualTo("application/json");
});
}
@ParameterizedWebClientTest
void retrieveJsonAsResponseEntity(ClientHttpConnector connector) {
void retrieveJsonAsResponseEntity(ClientHttpConnector connector) throws IOException {
startServer(connector);
String content = "{\"bar\":\"barbar\",\"foo\":\"foofoo\"}";
prepareResponse(response -> response
.setHeader("Content-Type", "application/json").setBody(content));
prepareResponse(builder -> builder
.setHeader("Content-Type", "application/json")
.body(content));
Mono<ResponseEntity<String>> result = this.webClient.get()
.uri("/json").accept(MediaType.APPLICATION_JSON)
@ -274,17 +277,18 @@ class WebClientIntegrationTests { @@ -274,17 +277,18 @@ class WebClientIntegrationTests {
expectRequestCount(1);
expectRequest(request -> {
assertThat(request.getPath()).isEqualTo("/json");
assertThat(request.getHeader(HttpHeaders.ACCEPT)).isEqualTo("application/json");
assertThat(request.getTarget()).isEqualTo("/json");
assertThat(request.getHeaders().get(HttpHeaders.ACCEPT)).isEqualTo("application/json");
});
}
@ParameterizedWebClientTest
void retrieveJsonAsBodilessEntity(ClientHttpConnector connector) {
void retrieveJsonAsBodilessEntity(ClientHttpConnector connector) throws IOException {
startServer(connector);
prepareResponse(response -> response
.setHeader("Content-Type", "application/json").setBody("{\"bar\":\"barbar\",\"foo\":\"foofoo\"}"));
prepareResponse(builder -> builder
.setHeader("Content-Type", "application/json")
.body("{\"bar\":\"barbar\",\"foo\":\"foofoo\"}"));
Mono<ResponseEntity<Void>> result = this.webClient.get()
.uri("/json").accept(MediaType.APPLICATION_JSON)
@ -302,18 +306,18 @@ class WebClientIntegrationTests { @@ -302,18 +306,18 @@ class WebClientIntegrationTests {
expectRequestCount(1);
expectRequest(request -> {
assertThat(request.getPath()).isEqualTo("/json");
assertThat(request.getHeader(HttpHeaders.ACCEPT)).isEqualTo("application/json");
assertThat(request.getTarget()).isEqualTo("/json");
assertThat(request.getHeaders().get(HttpHeaders.ACCEPT)).isEqualTo("application/json");
});
}
@ParameterizedWebClientTest
void retrieveJsonArray(ClientHttpConnector connector) {
void retrieveJsonArray(ClientHttpConnector connector) throws IOException {
startServer(connector);
prepareResponse(response -> response
prepareResponse(builder -> builder
.setHeader("Content-Type", "application/json")
.setBody("[{\"bar\":\"bar1\",\"foo\":\"foo1\"},{\"bar\":\"bar2\",\"foo\":\"foo2\"}]"));
.body("[{\"bar\":\"bar1\",\"foo\":\"foo1\"},{\"bar\":\"bar2\",\"foo\":\"foo2\"}]"));
Flux<Pojo> result = this.webClient.get()
.uri("/pojos")
@ -329,18 +333,19 @@ class WebClientIntegrationTests { @@ -329,18 +333,19 @@ class WebClientIntegrationTests {
expectRequestCount(1);
expectRequest(request -> {
assertThat(request.getPath()).isEqualTo("/pojos");
assertThat(request.getHeader(HttpHeaders.ACCEPT)).isEqualTo("application/json");
assertThat(request.getTarget()).isEqualTo("/pojos");
assertThat(request.getHeaders().get(HttpHeaders.ACCEPT)).isEqualTo("application/json");
});
}
@ParameterizedWebClientTest
void retrieveJsonArrayAsResponseEntityList(ClientHttpConnector connector) {
void retrieveJsonArrayAsResponseEntityList(ClientHttpConnector connector) throws IOException {
startServer(connector);
String content = "[{\"bar\":\"bar1\",\"foo\":\"foo1\"}, {\"bar\":\"bar2\",\"foo\":\"foo2\"}]";
prepareResponse(response -> response
.setHeader("Content-Type", "application/json").setBody(content));
prepareResponse(builder -> builder
.setHeader("Content-Type", "application/json")
.body(content));
Mono<ResponseEntity<List<Pojo>>> result = this.webClient.get()
.uri("/json").accept(MediaType.APPLICATION_JSON)
@ -360,18 +365,19 @@ class WebClientIntegrationTests { @@ -360,18 +365,19 @@ class WebClientIntegrationTests {
expectRequestCount(1);
expectRequest(request -> {
assertThat(request.getPath()).isEqualTo("/json");
assertThat(request.getHeader(HttpHeaders.ACCEPT)).isEqualTo("application/json");
assertThat(request.getTarget()).isEqualTo("/json");
assertThat(request.getHeaders().get(HttpHeaders.ACCEPT)).isEqualTo("application/json");
});
}
@ParameterizedWebClientTest
void retrieveJsonArrayAsResponseEntityFlux(ClientHttpConnector connector) {
void retrieveJsonArrayAsResponseEntityFlux(ClientHttpConnector connector) throws IOException {
startServer(connector);
String content = "[{\"bar\":\"bar1\",\"foo\":\"foo1\"}, {\"bar\":\"bar2\",\"foo\":\"foo2\"}]";
prepareResponse(response -> response
.setHeader("Content-Type", "application/json").setBody(content));
prepareResponse(builder -> builder
.setHeader("Content-Type", "application/json")
.body(content));
ResponseEntity<Flux<Pojo>> entity = this.webClient.get()
.uri("/json").accept(MediaType.APPLICATION_JSON)
@ -393,18 +399,19 @@ class WebClientIntegrationTests { @@ -393,18 +399,19 @@ class WebClientIntegrationTests {
expectRequestCount(1);
expectRequest(request -> {
assertThat(request.getPath()).isEqualTo("/json");
assertThat(request.getHeader(HttpHeaders.ACCEPT)).isEqualTo("application/json");
assertThat(request.getTarget()).isEqualTo("/json");
assertThat(request.getHeaders().get(HttpHeaders.ACCEPT)).isEqualTo("application/json");
});
}
@ParameterizedWebClientTest
void retrieveJsonArrayAsResponseEntityFluxWithBodyExtractor(ClientHttpConnector connector) {
void retrieveJsonArrayAsResponseEntityFluxWithBodyExtractor(ClientHttpConnector connector) throws IOException {
startServer(connector);
String content = "[{\"bar\":\"bar1\",\"foo\":\"foo1\"}, {\"bar\":\"bar2\",\"foo\":\"foo2\"}]";
prepareResponse(response -> response
.setHeader("Content-Type", "application/json").setBody(content));
prepareResponse(builder -> builder
.setHeader("Content-Type", "application/json")
.body(content));
ResponseEntity<Flux<Pojo>> entity = this.webClient.get()
.uri("/json").accept(MediaType.APPLICATION_JSON)
@ -426,13 +433,13 @@ class WebClientIntegrationTests { @@ -426,13 +433,13 @@ class WebClientIntegrationTests {
expectRequestCount(1);
expectRequest(request -> {
assertThat(request.getPath()).isEqualTo("/json");
assertThat(request.getHeader(HttpHeaders.ACCEPT)).isEqualTo("application/json");
assertThat(request.getTarget()).isEqualTo("/json");
assertThat(request.getHeaders().get(HttpHeaders.ACCEPT)).isEqualTo("application/json");
});
}
@Test // gh-24788
void retrieveJsonArrayAsBodilessEntityShouldReleasesConnection() {
void retrieveJsonArrayAsBodilessEntityShouldReleasesConnection() throws IOException {
// Constrain connection pool and make consecutive requests.
// 2nd request should hang if response was not drained.
@ -440,6 +447,7 @@ class WebClientIntegrationTests { @@ -440,6 +447,7 @@ class WebClientIntegrationTests {
ConnectionProvider connectionProvider = ConnectionProvider.create("test", 1);
this.server = new MockWebServer();
this.server.start();
WebClient webClient = WebClient
.builder()
.clientConnector(new ReactorClientHttpConnector(HttpClient.create(connectionProvider)))
@ -455,9 +463,9 @@ class WebClientIntegrationTests { @@ -455,9 +463,9 @@ class WebClientIntegrationTests {
.collect(Collectors.joining(",", "[", "]"))
.block();
prepareResponse(response -> response
prepareResponse(builder -> builder
.setHeader("Content-Type", "application/json")
.setBody(json));
.body(json));
Mono<ResponseEntity<Void>> result = webClient.get()
.uri("/json").accept(MediaType.APPLICATION_JSON)
@ -476,19 +484,20 @@ class WebClientIntegrationTests { @@ -476,19 +484,20 @@ class WebClientIntegrationTests {
expectRequestCount(i);
expectRequest(request -> {
assertThat(request.getPath()).isEqualTo("/json");
assertThat(request.getHeader(HttpHeaders.ACCEPT)).isEqualTo("application/json");
assertThat(request.getTarget()).isEqualTo("/json");
assertThat(request.getHeaders().get(HttpHeaders.ACCEPT)).isEqualTo("application/json");
});
}
}
@ParameterizedWebClientTest
void retrieveJsonAsSerializedText(ClientHttpConnector connector) {
void retrieveJsonAsSerializedText(ClientHttpConnector connector) throws IOException {
startServer(connector);
String content = "{\"bar\":\"barbar\",\"foo\":\"foofoo\"}";
prepareResponse(response -> response
.setHeader("Content-Type", "application/json").setBody(content));
prepareResponse(builder -> builder
.setHeader("Content-Type", "application/json")
.body(content));
Mono<String> result = this.webClient.get()
.uri("/json").accept(MediaType.APPLICATION_JSON)
@ -501,20 +510,20 @@ class WebClientIntegrationTests { @@ -501,20 +510,20 @@ class WebClientIntegrationTests {
expectRequestCount(1);
expectRequest(request -> {
assertThat(request.getPath()).isEqualTo("/json");
assertThat(request.getHeader(HttpHeaders.ACCEPT)).isEqualTo("application/json");
assertThat(request.getTarget()).isEqualTo("/json");
assertThat(request.getHeaders().get(HttpHeaders.ACCEPT)).isEqualTo("application/json");
});
}
@ParameterizedWebClientTest
@SuppressWarnings("rawtypes")
void retrieveJsonNull(ClientHttpConnector connector) {
void retrieveJsonNull(ClientHttpConnector connector) throws IOException {
startServer(connector);
prepareResponse(response -> response
.setResponseCode(200)
prepareResponse(builder -> builder
.code(200)
.setHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE)
.setBody("null"));
.body("null"));
Mono<Map> result = this.webClient.get()
.uri("/null")
@ -525,10 +534,11 @@ class WebClientIntegrationTests { @@ -525,10 +534,11 @@ class WebClientIntegrationTests {
}
@ParameterizedWebClientTest // SPR-15946
void retrieve404(ClientHttpConnector connector) {
void retrieve404(ClientHttpConnector connector) throws IOException {
startServer(connector);
prepareResponse(response -> response.setResponseCode(404)
prepareResponse(builder -> builder
.code(404)
.setHeader("Content-Type", "text/plain"));
Mono<String> result = this.webClient.get().uri("/greeting")
@ -541,17 +551,19 @@ class WebClientIntegrationTests { @@ -541,17 +551,19 @@ class WebClientIntegrationTests {
expectRequestCount(1);
expectRequest(request -> {
assertThat(request.getHeader(HttpHeaders.ACCEPT)).isEqualTo("*/*");
assertThat(request.getPath()).isEqualTo("/greeting");
assertThat(request.getHeaders().get(HttpHeaders.ACCEPT)).isEqualTo("*/*");
assertThat(request.getTarget()).isEqualTo("/greeting");
});
}
@ParameterizedWebClientTest
void retrieve404WithBody(ClientHttpConnector connector) {
void retrieve404WithBody(ClientHttpConnector connector) throws IOException {
startServer(connector);
prepareResponse(response -> response.setResponseCode(404)
.setHeader("Content-Type", "text/plain").setBody("Not Found"));
prepareResponse(builder -> builder
.code(404)
.setHeader("Content-Type", "text/plain")
.body("Not Found"));
Mono<String> result = this.webClient.get()
.uri("/greeting")
@ -564,19 +576,19 @@ class WebClientIntegrationTests { @@ -564,19 +576,19 @@ class WebClientIntegrationTests {
expectRequestCount(1);
expectRequest(request -> {
assertThat(request.getHeader(HttpHeaders.ACCEPT)).isEqualTo("*/*");
assertThat(request.getPath()).isEqualTo("/greeting");
assertThat(request.getHeaders().get(HttpHeaders.ACCEPT)).isEqualTo("*/*");
assertThat(request.getTarget()).isEqualTo("/greeting");
});
}
@ParameterizedWebClientTest
@SuppressWarnings("deprecation")
void retrieve500(ClientHttpConnector connector) {
void retrieve500(ClientHttpConnector connector) throws IOException {
startServer(connector);
String errorMessage = "Internal Server error";
prepareResponse(response -> response.setResponseCode(500)
.setHeader("Content-Type", "text/plain").setBody(errorMessage));
prepareResponse(builder -> builder.code(500)
.setHeader("Content-Type", "text/plain").body(errorMessage));
String path = "/greeting";
Mono<String> result = this.webClient.get()
@ -602,17 +614,17 @@ class WebClientIntegrationTests { @@ -602,17 +614,17 @@ class WebClientIntegrationTests {
expectRequestCount(1);
expectRequest(request -> {
assertThat(request.getHeader(HttpHeaders.ACCEPT)).isEqualTo("*/*");
assertThat(request.getPath()).isEqualTo(path);
assertThat(request.getHeaders().get(HttpHeaders.ACCEPT)).isEqualTo("*/*");
assertThat(request.getTarget()).isEqualTo(path);
});
}
@ParameterizedWebClientTest
void retrieve500AsEntity(ClientHttpConnector connector) {
void retrieve500AsEntity(ClientHttpConnector connector) throws IOException {
startServer(connector);
prepareResponse(response -> response.setResponseCode(500)
.setHeader("Content-Type", "text/plain").setBody("Internal Server error"));
prepareResponse(builder -> builder.code(500)
.setHeader("Content-Type", "text/plain").body("Internal Server error"));
Mono<ResponseEntity<String>> result = this.webClient.get()
.uri("/").accept(MediaType.APPLICATION_JSON)
@ -625,17 +637,17 @@ class WebClientIntegrationTests { @@ -625,17 +637,17 @@ class WebClientIntegrationTests {
expectRequestCount(1);
expectRequest(request -> {
assertThat(request.getPath()).isEqualTo("/");
assertThat(request.getHeader(HttpHeaders.ACCEPT)).isEqualTo("application/json");
assertThat(request.getTarget()).isEqualTo("/");
assertThat(request.getHeaders().get(HttpHeaders.ACCEPT)).isEqualTo("application/json");
});
}
@ParameterizedWebClientTest
void retrieve500AsEntityList(ClientHttpConnector connector) {
void retrieve500AsEntityList(ClientHttpConnector connector) throws IOException {
startServer(connector);
prepareResponse(response -> response.setResponseCode(500)
.setHeader("Content-Type", "text/plain").setBody("Internal Server error"));
prepareResponse(builder -> builder.code(500)
.setHeader("Content-Type", "text/plain").body("Internal Server error"));
Mono<ResponseEntity<List<String>>> result = this.webClient.get()
.uri("/").accept(MediaType.APPLICATION_JSON)
@ -648,17 +660,17 @@ class WebClientIntegrationTests { @@ -648,17 +660,17 @@ class WebClientIntegrationTests {
expectRequestCount(1);
expectRequest(request -> {
assertThat(request.getPath()).isEqualTo("/");
assertThat(request.getHeader(HttpHeaders.ACCEPT)).isEqualTo("application/json");
assertThat(request.getTarget()).isEqualTo("/");
assertThat(request.getHeaders().get(HttpHeaders.ACCEPT)).isEqualTo("application/json");
});
}
@ParameterizedWebClientTest
void retrieve500AsBodilessEntity(ClientHttpConnector connector) {
void retrieve500AsBodilessEntity(ClientHttpConnector connector) throws IOException {
startServer(connector);
prepareResponse(response -> response.setResponseCode(500)
.setHeader("Content-Type", "text/plain").setBody("Internal Server error"));
prepareResponse(builder -> builder.code(500)
.setHeader("Content-Type", "text/plain").body("Internal Server error"));
Mono<ResponseEntity<Void>> result = this.webClient.get()
.uri("/").accept(MediaType.APPLICATION_JSON)
@ -671,24 +683,24 @@ class WebClientIntegrationTests { @@ -671,24 +683,24 @@ class WebClientIntegrationTests {
expectRequestCount(1);
expectRequest(request -> {
assertThat(request.getPath()).isEqualTo("/");
assertThat(request.getHeader(HttpHeaders.ACCEPT)).isEqualTo("application/json");
assertThat(request.getTarget()).isEqualTo("/");
assertThat(request.getHeaders().get(HttpHeaders.ACCEPT)).isEqualTo("application/json");
});
}
@ParameterizedWebClientTest
@SuppressWarnings("deprecation")
void retrieve555UnknownStatus(ClientHttpConnector connector) {
void retrieve555UnknownStatus(ClientHttpConnector connector) throws IOException {
startServer(connector);
int errorStatus = 555;
assertThat(HttpStatus.resolve(errorStatus)).isNull();
String errorMessage = "Something went wrong";
prepareResponse(response ->
response.setResponseCode(errorStatus)
.setHeader("Content-Type", "text/plain")
.setBody(errorMessage));
prepareResponse(builder -> builder
.code(errorStatus)
.setHeader("Content-Type", "text/plain")
.body(errorMessage));
Mono<String> result = this.webClient.get().uri("/unknownPage").retrieve().bodyToMono(String.class);
@ -705,23 +717,23 @@ class WebClientIntegrationTests { @@ -705,23 +717,23 @@ class WebClientIntegrationTests {
expectRequestCount(1);
expectRequest(request -> {
assertThat(request.getHeader(HttpHeaders.ACCEPT)).isEqualTo("*/*");
assertThat(request.getPath()).isEqualTo("/unknownPage");
assertThat(request.getHeaders().get(HttpHeaders.ACCEPT)).isEqualTo("*/*");
assertThat(request.getTarget()).isEqualTo("/unknownPage");
});
}
@ParameterizedWebClientTest // gh-31202
void retrieve929UnknownStatusCode(ClientHttpConnector connector) {
void retrieve929UnknownStatusCode(ClientHttpConnector connector) throws IOException {
startServer(connector);
int errorStatus = 929;
assertThat(HttpStatus.resolve(errorStatus)).isNull();
String errorMessage = "Something went wrong";
prepareResponse(response ->
response.setResponseCode(errorStatus)
prepareResponse(builder ->
builder.code(errorStatus)
.setHeader("Content-Type", "text/plain")
.setBody(errorMessage));
.body(errorMessage));
Mono<String> result = this.webClient.get().uri("/unknownPage").retrieve().bodyToMono(String.class);
@ -739,17 +751,17 @@ class WebClientIntegrationTests { @@ -739,17 +751,17 @@ class WebClientIntegrationTests {
expectRequestCount(1);
expectRequest(request -> {
assertThat(request.getHeader(HttpHeaders.ACCEPT)).isEqualTo("*/*");
assertThat(request.getPath()).isEqualTo("/unknownPage");
assertThat(request.getHeaders().get(HttpHeaders.ACCEPT)).isEqualTo("*/*");
assertThat(request.getTarget()).isEqualTo("/unknownPage");
});
}
@ParameterizedWebClientTest
void postPojoAsJson(ClientHttpConnector connector) {
void postPojoAsJson(ClientHttpConnector connector) throws IOException {
startServer(connector);
prepareResponse(response -> response.setHeader("Content-Type", "application/json")
.setBody("{\"bar\":\"BARBAR\",\"foo\":\"FOOFOO\"}"));
prepareResponse(builder -> builder.setHeader("Content-Type", "application/json")
.body("{\"bar\":\"BARBAR\",\"foo\":\"FOOFOO\"}"));
Mono<Pojo> result = this.webClient.post()
.uri("/pojo/capitalize")
@ -766,19 +778,19 @@ class WebClientIntegrationTests { @@ -766,19 +778,19 @@ class WebClientIntegrationTests {
expectRequestCount(1);
expectRequest(request -> {
assertThat(request.getPath()).isEqualTo("/pojo/capitalize");
assertThat(request.getBody().readUtf8()).isEqualTo("{\"bar\":\"barbar\",\"foo\":\"foofoo\"}");
assertThat(request.getHeader(HttpHeaders.CONTENT_LENGTH)).isEqualTo("31");
assertThat(request.getHeader(HttpHeaders.ACCEPT)).isEqualTo("application/json");
assertThat(request.getHeader(HttpHeaders.CONTENT_TYPE)).isEqualTo("application/json");
assertThat(request.getTarget()).isEqualTo("/pojo/capitalize");
assertThat(request.getBody().utf8()).isEqualTo("{\"bar\":\"barbar\",\"foo\":\"foofoo\"}");
assertThat(request.getHeaders().get(HttpHeaders.CONTENT_LENGTH)).isEqualTo("31");
assertThat(request.getHeaders().get(HttpHeaders.ACCEPT)).isEqualTo("application/json");
assertThat(request.getHeaders().get(HttpHeaders.CONTENT_TYPE)).isEqualTo("application/json");
});
}
@ParameterizedWebClientTest // SPR-16246
void postLargeTextFile(ClientHttpConnector connector) {
void postLargeTextFile(ClientHttpConnector connector) throws IOException {
startServer(connector);
prepareResponse(response -> {});
prepareResponse(Function.identity());
Resource resource = new ClassPathResource("largeTextFile.txt", getClass());
Flux<DataBuffer> body = DataBufferUtils.read(resource, DefaultDataBufferFactory.sharedInstance, 4096);
@ -794,10 +806,8 @@ class WebClientIntegrationTests { @@ -794,10 +806,8 @@ class WebClientIntegrationTests {
.verify(Duration.ofSeconds(5));
expectRequest(request -> {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
try {
request.getBody().copyTo(bos);
String actual = bos.toString(StandardCharsets.UTF_8);
String actual = request.getBody().utf8();
String expected = Files.readString(resource.getFile().toPath(), StandardCharsets.UTF_8);
assertThat(actual).isEqualTo(expected);
}
@ -808,11 +818,11 @@ class WebClientIntegrationTests { @@ -808,11 +818,11 @@ class WebClientIntegrationTests {
}
@ParameterizedWebClientTest
void statusHandler(ClientHttpConnector connector) {
void statusHandler(ClientHttpConnector connector) throws IOException {
startServer(connector);
prepareResponse(response -> response.setResponseCode(500)
.setHeader("Content-Type", "text/plain").setBody("Internal Server error"));
prepareResponse(builder -> builder.code(500)
.setHeader("Content-Type", "text/plain").body("Internal Server error"));
Mono<String> result = this.webClient.get()
.uri("/greeting")
@ -826,17 +836,17 @@ class WebClientIntegrationTests { @@ -826,17 +836,17 @@ class WebClientIntegrationTests {
expectRequestCount(1);
expectRequest(request -> {
assertThat(request.getHeader(HttpHeaders.ACCEPT)).isEqualTo("*/*");
assertThat(request.getPath()).isEqualTo("/greeting");
assertThat(request.getHeaders().get(HttpHeaders.ACCEPT)).isEqualTo("*/*");
assertThat(request.getTarget()).isEqualTo("/greeting");
});
}
@ParameterizedWebClientTest
void statusHandlerParameterizedTypeReference(ClientHttpConnector connector) {
void statusHandlerParameterizedTypeReference(ClientHttpConnector connector) throws IOException {
startServer(connector);
prepareResponse(response -> response.setResponseCode(500)
.setHeader("Content-Type", "text/plain").setBody("Internal Server error"));
prepareResponse(builder -> builder.code(500)
.setHeader("Content-Type", "text/plain").body("Internal Server error"));
Mono<String> result = this.webClient.get()
.uri("/greeting")
@ -850,19 +860,19 @@ class WebClientIntegrationTests { @@ -850,19 +860,19 @@ class WebClientIntegrationTests {
expectRequestCount(1);
expectRequest(request -> {
assertThat(request.getHeader(HttpHeaders.ACCEPT)).isEqualTo("*/*");
assertThat(request.getPath()).isEqualTo("/greeting");
assertThat(request.getHeaders().get(HttpHeaders.ACCEPT)).isEqualTo("*/*");
assertThat(request.getTarget()).isEqualTo("/greeting");
});
}
@ParameterizedWebClientTest
void statusHandlerWithErrorBodyTransformation(ClientHttpConnector connector) {
void statusHandlerWithErrorBodyTransformation(ClientHttpConnector connector) throws IOException {
startServer(connector);
prepareResponse(response -> response
.setResponseCode(500)
prepareResponse(builder -> builder
.code(500)
.setHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE)
.setBody("{\"bar\":\"barbar\",\"foo\":\"foofoo\"}")
.body("{\"bar\":\"barbar\",\"foo\":\"foofoo\"}")
);
Mono<String> result = this.webClient.get()
@ -884,11 +894,12 @@ class WebClientIntegrationTests { @@ -884,11 +894,12 @@ class WebClientIntegrationTests {
}
@ParameterizedWebClientTest
void statusHandlerRawStatus(ClientHttpConnector connector) {
void statusHandlerRawStatus(ClientHttpConnector connector) throws IOException {
startServer(connector);
prepareResponse(response -> response.setResponseCode(500)
.setHeader("Content-Type", "text/plain").setBody("Internal Server error"));
prepareResponse(builder -> builder.code(500)
.setHeader("Content-Type", "text/plain").body("Internal Server error")
);
Mono<String> result = this.webClient.get()
.uri("/greeting")
@ -902,17 +913,17 @@ class WebClientIntegrationTests { @@ -902,17 +913,17 @@ class WebClientIntegrationTests {
expectRequestCount(1);
expectRequest(request -> {
assertThat(request.getHeader(HttpHeaders.ACCEPT)).isEqualTo("*/*");
assertThat(request.getPath()).isEqualTo("/greeting");
assertThat(request.getHeaders().get(HttpHeaders.ACCEPT)).isEqualTo("*/*");
assertThat(request.getTarget()).isEqualTo("/greeting");
});
}
@ParameterizedWebClientTest
void statusHandlerSuppressedErrorSignal(ClientHttpConnector connector) {
void statusHandlerSuppressedErrorSignal(ClientHttpConnector connector) throws IOException {
startServer(connector);
prepareResponse(response -> response.setResponseCode(500)
.setHeader("Content-Type", "text/plain").setBody("Internal Server error"));
prepareResponse(builder -> builder.code(500)
.setHeader("Content-Type", "text/plain").body("Internal Server error"));
Mono<String> result = this.webClient.get()
.uri("/greeting")
@ -926,18 +937,18 @@ class WebClientIntegrationTests { @@ -926,18 +937,18 @@ class WebClientIntegrationTests {
expectRequestCount(1);
expectRequest(request -> {
assertThat(request.getHeader(HttpHeaders.ACCEPT)).isEqualTo("*/*");
assertThat(request.getPath()).isEqualTo("/greeting");
assertThat(request.getHeaders().get(HttpHeaders.ACCEPT)).isEqualTo("*/*");
assertThat(request.getTarget()).isEqualTo("/greeting");
});
}
@ParameterizedWebClientTest
void statusHandlerSuppressedErrorSignalWithFlux(ClientHttpConnector connector) {
void statusHandlerSuppressedErrorSignalWithFlux(ClientHttpConnector connector) throws IOException {
startServer(connector);
prepareResponse(response -> response.setResponseCode(500)
.setHeader("Content-Type", "text/plain").setBody("Internal Server error"));
prepareResponse(builder -> builder.code(500)
.setHeader("Content-Type", "text/plain").body("Internal Server error"));
Flux<String> result = this.webClient.get()
.uri("/greeting")
@ -951,18 +962,18 @@ class WebClientIntegrationTests { @@ -951,18 +962,18 @@ class WebClientIntegrationTests {
expectRequestCount(1);
expectRequest(request -> {
assertThat(request.getHeader(HttpHeaders.ACCEPT)).isEqualTo("*/*");
assertThat(request.getPath()).isEqualTo("/greeting");
assertThat(request.getHeaders().get(HttpHeaders.ACCEPT)).isEqualTo("*/*");
assertThat(request.getTarget()).isEqualTo("/greeting");
});
}
@ParameterizedWebClientTest
void statusHandlerSuppressedErrorSignalWithEntity(ClientHttpConnector connector) {
void statusHandlerSuppressedErrorSignalWithEntity(ClientHttpConnector connector) throws IOException {
startServer(connector);
String content = "Internal Server error";
prepareResponse(response -> response.setResponseCode(500)
.setHeader("Content-Type", "text/plain").setBody(content));
prepareResponse(builder -> builder.code(500)
.setHeader("Content-Type", "text/plain").body(content));
Mono<ResponseEntity<String>> result = this.webClient.get()
.uri("/").accept(MediaType.APPLICATION_JSON)
@ -980,16 +991,16 @@ class WebClientIntegrationTests { @@ -980,16 +991,16 @@ class WebClientIntegrationTests {
expectRequestCount(1);
expectRequest(request -> {
assertThat(request.getPath()).isEqualTo("/");
assertThat(request.getHeader(HttpHeaders.ACCEPT)).isEqualTo("application/json");
assertThat(request.getTarget()).isEqualTo("/");
assertThat(request.getHeaders().get(HttpHeaders.ACCEPT)).isEqualTo("application/json");
});
}
@ParameterizedWebClientTest
void exchangeForPlainText(ClientHttpConnector connector) {
void exchangeForPlainText(ClientHttpConnector connector) throws IOException {
startServer(connector);
prepareResponse(response -> response.setBody("Hello Spring!"));
prepareResponse(builder -> builder.body("Hello Spring!"));
Mono<String> result = this.webClient.get()
.uri("/greeting")
@ -1002,19 +1013,19 @@ class WebClientIntegrationTests { @@ -1002,19 +1013,19 @@ class WebClientIntegrationTests {
expectRequestCount(1);
expectRequest(request -> {
assertThat(request.getHeader("X-Test-Header")).isEqualTo("testvalue");
assertThat(request.getHeader(HttpHeaders.ACCEPT)).isEqualTo("*/*");
assertThat(request.getPath()).isEqualTo("/greeting");
assertThat(request.getHeaders().get("X-Test-Header")).isEqualTo("testvalue");
assertThat(request.getHeaders().get(HttpHeaders.ACCEPT)).isEqualTo("*/*");
assertThat(request.getTarget()).isEqualTo("/greeting");
});
}
@ParameterizedWebClientTest
void exchangeForJsonAsResponseEntity(ClientHttpConnector connector) {
void exchangeForJsonAsResponseEntity(ClientHttpConnector connector) throws IOException {
startServer(connector);
String content = "{\"bar\":\"barbar\",\"foo\":\"foofoo\"}";
prepareResponse(response -> response
.setHeader("Content-Type", "application/json").setBody(content));
prepareResponse(builder -> builder
.setHeader("Content-Type", "application/json").body(content));
Mono<ResponseEntity<Pojo>> result = this.webClient.get()
.uri("/json").accept(MediaType.APPLICATION_JSON)
@ -1031,17 +1042,17 @@ class WebClientIntegrationTests { @@ -1031,17 +1042,17 @@ class WebClientIntegrationTests {
expectRequestCount(1);
expectRequest(request -> {
assertThat(request.getPath()).isEqualTo("/json");
assertThat(request.getHeader(HttpHeaders.ACCEPT)).isEqualTo("application/json");
assertThat(request.getTarget()).isEqualTo("/json");
assertThat(request.getHeaders().get(HttpHeaders.ACCEPT)).isEqualTo("application/json");
});
}
@ParameterizedWebClientTest
void exchangeForJsonAsBodilessEntity(ClientHttpConnector connector) {
void exchangeForJsonAsBodilessEntity(ClientHttpConnector connector) throws IOException {
startServer(connector);
prepareResponse(response -> response
.setHeader("Content-Type", "application/json").setBody("{\"bar\":\"barbar\",\"foo\":\"foofoo\"}"));
prepareResponse(builder -> builder
.setHeader("Content-Type", "application/json").body("{\"bar\":\"barbar\",\"foo\":\"foofoo\"}"));
Mono<ResponseEntity<Void>> result = this.webClient.get()
.uri("/json").accept(MediaType.APPLICATION_JSON)
@ -1058,18 +1069,18 @@ class WebClientIntegrationTests { @@ -1058,18 +1069,18 @@ class WebClientIntegrationTests {
expectRequestCount(1);
expectRequest(request -> {
assertThat(request.getPath()).isEqualTo("/json");
assertThat(request.getHeader(HttpHeaders.ACCEPT)).isEqualTo("application/json");
assertThat(request.getTarget()).isEqualTo("/json");
assertThat(request.getHeaders().get(HttpHeaders.ACCEPT)).isEqualTo("application/json");
});
}
@ParameterizedWebClientTest
void exchangeForJsonArrayAsResponseEntity(ClientHttpConnector connector) {
void exchangeForJsonArrayAsResponseEntity(ClientHttpConnector connector) throws IOException {
startServer(connector);
String content = "[{\"bar\":\"bar1\",\"foo\":\"foo1\"}, {\"bar\":\"bar2\",\"foo\":\"foo2\"}]";
prepareResponse(response -> response
.setHeader("Content-Type", "application/json").setBody(content));
prepareResponse(builder -> builder
.setHeader("Content-Type", "application/json").body(content));
Mono<ResponseEntity<List<Pojo>>> result = this.webClient.get()
.uri("/json").accept(MediaType.APPLICATION_JSON)
@ -1088,16 +1099,16 @@ class WebClientIntegrationTests { @@ -1088,16 +1099,16 @@ class WebClientIntegrationTests {
expectRequestCount(1);
expectRequest(request -> {
assertThat(request.getPath()).isEqualTo("/json");
assertThat(request.getHeader(HttpHeaders.ACCEPT)).isEqualTo("application/json");
assertThat(request.getTarget()).isEqualTo("/json");
assertThat(request.getHeaders().get(HttpHeaders.ACCEPT)).isEqualTo("application/json");
});
}
@ParameterizedWebClientTest
void exchangeForEmptyBodyAsVoidEntity(ClientHttpConnector connector) {
void exchangeForEmptyBodyAsVoidEntity(ClientHttpConnector connector) throws IOException {
startServer(connector);
prepareResponse(response -> response.setHeader("Content-Length", "0").setBody(""));
prepareResponse(builder -> builder.addHeader("Content-Length", "0").body(""));
Mono<ResponseEntity<Void>> result = this.webClient.get()
.uri("/noContent")
@ -1109,11 +1120,11 @@ class WebClientIntegrationTests { @@ -1109,11 +1120,11 @@ class WebClientIntegrationTests {
}
@ParameterizedWebClientTest
void exchangeFor404(ClientHttpConnector connector) {
void exchangeFor404(ClientHttpConnector connector) throws IOException {
startServer(connector);
prepareResponse(response -> response.setResponseCode(404)
.setHeader("Content-Type", "text/plain").setBody("Not Found"));
prepareResponse(builder -> builder.code(404)
.setHeader("Content-Type", "text/plain").body("Not Found"));
Mono<ResponseEntity<Void>> result = this.webClient.get().uri("/greeting")
.exchangeToMono(ClientResponse::toBodilessEntity);
@ -1125,20 +1136,20 @@ class WebClientIntegrationTests { @@ -1125,20 +1136,20 @@ class WebClientIntegrationTests {
expectRequestCount(1);
expectRequest(request -> {
assertThat(request.getHeader(HttpHeaders.ACCEPT)).isEqualTo("*/*");
assertThat(request.getPath()).isEqualTo("/greeting");
assertThat(request.getHeaders().get(HttpHeaders.ACCEPT)).isEqualTo("*/*");
assertThat(request.getTarget()).isEqualTo("/greeting");
});
}
@ParameterizedWebClientTest
void exchangeForUnknownStatusCode(ClientHttpConnector connector) {
void exchangeForUnknownStatusCode(ClientHttpConnector connector) throws IOException {
startServer(connector);
int errorStatus = 555;
assertThat(HttpStatus.resolve(errorStatus)).isNull();
String errorMessage = "Something went wrong";
prepareResponse(response -> response.setResponseCode(errorStatus)
.setHeader("Content-Type", "text/plain").setBody(errorMessage));
prepareResponse(builder -> builder.code(errorStatus)
.setHeader("Content-Type", "text/plain").body(errorMessage));
Mono<ResponseEntity<Void>> result = this.webClient.get()
.uri("/unknownPage")
@ -1151,17 +1162,17 @@ class WebClientIntegrationTests { @@ -1151,17 +1162,17 @@ class WebClientIntegrationTests {
expectRequestCount(1);
expectRequest(request -> {
assertThat(request.getHeader(HttpHeaders.ACCEPT)).isEqualTo("*/*");
assertThat(request.getPath()).isEqualTo("/unknownPage");
assertThat(request.getHeaders().get(HttpHeaders.ACCEPT)).isEqualTo("*/*");
assertThat(request.getTarget()).isEqualTo("/unknownPage");
});
}
@ParameterizedWebClientTest
void filter(ClientHttpConnector connector) {
void filter(ClientHttpConnector connector) throws IOException {
startServer(connector);
prepareResponse(response -> response.setHeader("Content-Type", "text/plain")
.setBody("Hello Spring!"));
prepareResponse(builder -> builder.setHeader("Content-Type", "text/plain")
.body("Hello Spring!"));
WebClient filteredClient = this.webClient.mutate()
.filter((request, next) -> {
@ -1182,11 +1193,11 @@ class WebClientIntegrationTests { @@ -1182,11 +1193,11 @@ class WebClientIntegrationTests {
.verify(Duration.ofSeconds(3));
expectRequestCount(1);
expectRequest(request -> assertThat(request.getHeader("foo")).isEqualTo("bar"));
expectRequest(request -> assertThat(request.getHeaders().get("foo")).isEqualTo("bar"));
}
@ParameterizedWebClientTest
void filterForErrorHandling(ClientHttpConnector connector) {
void filterForErrorHandling(ClientHttpConnector connector) throws IOException {
startServer(connector);
ExchangeFilterFunction filter = ExchangeFilterFunction.ofResponseProcessor(
@ -1201,8 +1212,9 @@ class WebClientIntegrationTests { @@ -1201,8 +1212,9 @@ class WebClientIntegrationTests {
WebClient filteredClient = this.webClient.mutate().filter(filter).build();
// header not present
prepareResponse(response -> response
.setHeader("Content-Type", "text/plain").setBody("Hello Spring!"));
prepareResponse(builder -> builder
.setHeader("Content-Type", "text/plain")
.body("Hello Spring!"));
Mono<String> result = filteredClient.get()
.uri("/greeting")
@ -1214,9 +1226,9 @@ class WebClientIntegrationTests { @@ -1214,9 +1226,9 @@ class WebClientIntegrationTests {
// header present
prepareResponse(response -> response.setHeader("Content-Type", "text/plain")
prepareResponse(builder -> builder.setHeader("Content-Type", "text/plain")
.setHeader("Foo", "Bar")
.setBody("Hello Spring!"));
.body("Hello Spring!"));
result = filteredClient.get()
.uri("/greeting")
@ -1230,14 +1242,14 @@ class WebClientIntegrationTests { @@ -1230,14 +1242,14 @@ class WebClientIntegrationTests {
}
@ParameterizedWebClientTest
void exchangeResponseCookies(ClientHttpConnector connector) {
void exchangeResponseCookies(ClientHttpConnector connector) throws IOException {
startServer(connector);
prepareResponse(response -> response
prepareResponse(builder -> builder
.setHeader("Content-Type", "text/plain")
.addHeader("Set-Cookie", "testkey1=testvalue1") // TODO invalid ";" at the end
.addHeader("Set-Cookie", "testkey2=testvalue2; Max-Age=42; HttpOnly; SameSite=Lax; Secure")
.setBody("test"));
.body("test"));
this.webClient.get()
.uri("/test")
@ -1289,12 +1301,12 @@ class WebClientIntegrationTests { @@ -1289,12 +1301,12 @@ class WebClientIntegrationTests {
}
@ParameterizedWebClientTest
void retrieveTextDecodedToFlux(ClientHttpConnector connector) {
void retrieveTextDecodedToFlux(ClientHttpConnector connector) throws IOException {
startServer(connector);
prepareResponse(response -> response
.setHeader("Content-Type", "text/plain")
.setBody("Hey now"));
prepareResponse(builder -> builder
.addHeader("Content-Type", "text/plain")
.body("Hey now"));
Flux<String> result = this.webClient.get()
.uri("/")
@ -1350,10 +1362,9 @@ class WebClientIntegrationTests { @@ -1350,10 +1362,9 @@ class WebClientIntegrationTests {
});
}
private void prepareResponse(Consumer<MockResponse> consumer) {
MockResponse response = new MockResponse();
consumer.accept(response);
this.server.enqueue(response);
private void prepareResponse(Function<MockResponse.Builder, MockResponse.Builder> f) {
MockResponse.Builder builder = new MockResponse.Builder();
this.server.enqueue(f.apply(builder).build());
}
private void expectRequest(Consumer<RecordedRequest> consumer) {

33
spring-webflux/src/test/java/org/springframework/web/reactive/function/client/WebClientVersionTests.java

@ -19,9 +19,9 @@ package org.springframework.web.reactive.function.client; @@ -19,9 +19,9 @@ package org.springframework.web.reactive.function.client;
import java.io.IOException;
import java.util.function.Consumer;
import okhttp3.mockwebserver.MockResponse;
import okhttp3.mockwebserver.MockWebServer;
import okhttp3.mockwebserver.RecordedRequest;
import mockwebserver3.MockResponse;
import mockwebserver3.MockWebServer;
import mockwebserver3.RecordedRequest;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
@ -39,45 +39,48 @@ public class WebClientVersionTests { @@ -39,45 +39,48 @@ public class WebClientVersionTests {
private final MockWebServer server = new MockWebServer();
private final WebClient.Builder webClientBuilder =
WebClient.builder().baseUrl(this.server.url("/").toString());
private WebClient.Builder webClientBuilder;
@BeforeEach
void setUp() {
MockResponse response = new MockResponse();
response.setHeader("Content-Type", "text/plain").setBody("body");
void setUp() throws IOException {
this.server.start();
this.webClientBuilder = WebClient.builder().baseUrl(this.server.url("/").toString());
MockResponse response = new MockResponse.Builder()
.setHeader("Content-Type", "text/plain")
.body("body")
.build();
this.server.enqueue(response);
}
@AfterEach
void shutdown() throws IOException {
this.server.shutdown();
void shutdown() {
this.server.close();
}
@Test
void header() {
performRequest(ApiVersionInserter.useHeader("X-API-Version"));
expectRequest(request -> assertThat(request.getHeader("X-API-Version")).isEqualTo("1.2"));
expectRequest(request -> assertThat(request.getHeaders().get("X-API-Version")).isEqualTo("1.2"));
}
@Test
void queryParam() {
performRequest(ApiVersionInserter.useQueryParam("api-version"));
expectRequest(request -> assertThat(request.getPath()).isEqualTo("/path?api-version=1.2"));
expectRequest(request -> assertThat(request.getTarget()).isEqualTo("/path?api-version=1.2"));
}
@Test
void pathSegmentIndexLessThanSize() {
performRequest(ApiVersionInserter.builder().usePathSegment(0).withVersionFormatter(v -> "v" + v).build());
expectRequest(request -> assertThat(request.getPath()).isEqualTo("/v1.2/path"));
expectRequest(request -> assertThat(request.getTarget()).isEqualTo("/v1.2/path"));
}
@Test
void pathSegmentIndexEqualToSize() {
performRequest(ApiVersionInserter.builder().usePathSegment(1).withVersionFormatter(v -> "v" + v).build());
expectRequest(request -> assertThat(request.getPath()).isEqualTo("/path/v1.2"));
expectRequest(request -> assertThat(request.getTarget()).isEqualTo("/path/v1.2"));
}
@Test
@ -93,7 +96,7 @@ public class WebClientVersionTests { @@ -93,7 +96,7 @@ public class WebClientVersionTests {
WebClient webClient = webClientBuilder.defaultApiVersion(1.2).apiVersionInserter(inserter).build();
webClient.get().uri("/path").retrieve().bodyToMono(String.class).block();
expectRequest(request -> assertThat(request.getHeader("X-API-Version")).isEqualTo("1.2"));
expectRequest(request -> assertThat(request.getHeaders().get("X-API-Version")).isEqualTo("1.2"));
}
private void performRequest(ApiVersionInserter versionInserter) {

68
spring-webflux/src/test/java/org/springframework/web/reactive/function/client/support/WebClientAdapterTests.java

@ -24,11 +24,11 @@ import java.util.HashMap; @@ -24,11 +24,11 @@ import java.util.HashMap;
import java.util.LinkedHashSet;
import java.util.Map;
import java.util.Set;
import java.util.function.Consumer;
import java.util.function.Function;
import okhttp3.mockwebserver.MockResponse;
import okhttp3.mockwebserver.MockWebServer;
import okhttp3.mockwebserver.RecordedRequest;
import mockwebserver3.MockResponse;
import mockwebserver3.MockWebServer;
import mockwebserver3.RecordedRequest;
import org.jspecify.annotations.Nullable;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
@ -75,27 +75,29 @@ class WebClientAdapterTests { @@ -75,27 +75,29 @@ class WebClientAdapterTests {
@BeforeEach
void setUp() {
void setUp() throws IOException {
this.server = new MockWebServer();
this.server.start();
this.anotherServer = anotherServer();
this.anotherServer.start();
}
@SuppressWarnings("ConstantConditions")
@AfterEach
void shutdown() throws IOException {
void shutdown() {
if (this.server != null) {
this.server.shutdown();
this.server.close();
}
if (this.anotherServer != null) {
this.anotherServer.shutdown();
this.anotherServer.close();
}
}
@Test
void greeting() {
prepareResponse(response -> response.setHeader("Content-Type", "text/plain").setBody("Hello Spring!"));
prepareResponse(builder -> builder.setHeader("Content-Type", "text/plain").body("Hello Spring!"));
StepVerifier.create(initService().getGreeting())
.expectNext("Hello Spring!")
@ -115,7 +117,7 @@ class WebClientAdapterTests { @@ -115,7 +117,7 @@ class WebClientAdapterTests {
})
.build();
prepareResponse(response -> response.setHeader("Content-Type", "text/plain").setBody("Hello Spring!"));
prepareResponse(response -> response.setHeader("Content-Type", "text/plain").body("Hello Spring!"));
StepVerifier.create(initService(webClient).getGreetingWithAttribute("myAttributeValue"))
.expectNext("Hello Spring!")
@ -128,18 +130,18 @@ class WebClientAdapterTests { @@ -128,18 +130,18 @@ class WebClientAdapterTests {
@Test // gh-29624
void uri() throws Exception {
String expectedBody = "hello";
prepareResponse(response -> response.setResponseCode(200).setBody(expectedBody));
prepareResponse(response -> response.code(200).body(expectedBody));
URI dynamicUri = this.server.url("/greeting/123").uri();
String actualBody = initService().getGreetingById(dynamicUri, "456");
assertThat(actualBody).isEqualTo(expectedBody);
assertThat(this.server.takeRequest().getRequestUrl().uri()).isEqualTo(dynamicUri);
assertThat(this.server.takeRequest().getUrl().uri()).isEqualTo(dynamicUri);
}
@Test
void formData() throws Exception {
prepareResponse(response -> response.setResponseCode(201));
prepareResponse(response -> response.code(201));
MultiValueMap<String, String> map = new LinkedMultiValueMap<>();
map.add("param1", "value 1");
@ -149,12 +151,12 @@ class WebClientAdapterTests { @@ -149,12 +151,12 @@ class WebClientAdapterTests {
RecordedRequest request = this.server.takeRequest();
assertThat(request.getHeaders().get("Content-Type")).isEqualTo("application/x-www-form-urlencoded");
assertThat(request.getBody().readUtf8()).isEqualTo("param1=value+1&param2=value+2");
assertThat(request.getBody().utf8()).isEqualTo("param1=value+1&param2=value+2");
}
@Test // gh-30342
void multipart() throws InterruptedException {
prepareResponse(response -> response.setResponseCode(201));
prepareResponse(response -> response.code(201));
String fileName = "testFileName";
String originalFileName = "originalTestFileName";
MultipartFile file = new MockMultipartFile(
@ -164,7 +166,7 @@ class WebClientAdapterTests { @@ -164,7 +166,7 @@ class WebClientAdapterTests {
RecordedRequest request = this.server.takeRequest();
assertThat(request.getHeaders().get("Content-Type")).startsWith("multipart/form-data;boundary=");
assertThat(request.getBody().readUtf8())
assertThat(request.getBody().utf8())
.containsSubsequence("Content-Disposition: form-data; name=\"file\"; filename=\"originalTestFileName\"",
"Content-Type: application/json", "Content-Length: 4", "test",
"Content-Disposition: form-data; name=\"anotherPart\"",
@ -173,7 +175,7 @@ class WebClientAdapterTests { @@ -173,7 +175,7 @@ class WebClientAdapterTests {
@Test // gh-34793
void postSet() throws InterruptedException {
prepareResponse(response -> response.setResponseCode(201));
prepareResponse(response -> response.code(201));
Set<Person> persons = new LinkedHashSet<>();
persons.add(new Person("John"));
@ -183,54 +185,53 @@ class WebClientAdapterTests { @@ -183,54 +185,53 @@ class WebClientAdapterTests {
RecordedRequest request = server.takeRequest();
assertThat(request.getMethod()).isEqualTo("POST");
assertThat(request.getPath()).isEqualTo("/persons");
assertThat(request.getBody().readUtf8()).isEqualTo("[{\"name\":\"John\"},{\"name\":\"Richard\"}]");
assertThat(request.getTarget()).isEqualTo("/persons");
assertThat(request.getBody().utf8()).isEqualTo("[{\"name\":\"John\"},{\"name\":\"Richard\"}]");
}
@Test
void uriBuilderFactory() throws Exception {
String ignoredResponseBody = "hello";
prepareResponse(response -> response.setResponseCode(200).setBody(ignoredResponseBody));
prepareResponse(response -> response.code(200).body(ignoredResponseBody));
UriBuilderFactory factory = new DefaultUriBuilderFactory(this.anotherServer.url("/").toString());
String actualBody = initService().getWithUriBuilderFactory(factory);
assertThat(actualBody).isEqualTo(ANOTHER_SERVER_RESPONSE_BODY);
assertThat(this.anotherServer.takeRequest().getPath()).isEqualTo("/greeting");
assertThat(this.anotherServer.takeRequest().getTarget()).isEqualTo("/greeting");
assertThat(this.server.getRequestCount()).isEqualTo(0);
}
@Test
void uriBuilderFactoryWithPathVariableAndRequestParam() throws Exception {
String ignoredResponseBody = "hello";
prepareResponse(response -> response.setResponseCode(200).setBody(ignoredResponseBody));
prepareResponse(response -> response.code(200).body(ignoredResponseBody));
UriBuilderFactory factory = new DefaultUriBuilderFactory(this.anotherServer.url("/").toString());
String actualBody = initService().getWithUriBuilderFactory(factory, "123", "test");
assertThat(actualBody).isEqualTo(ANOTHER_SERVER_RESPONSE_BODY);
assertThat(this.anotherServer.takeRequest().getPath()).isEqualTo("/greeting/123?param=test");
assertThat(this.anotherServer.takeRequest().getTarget()).isEqualTo("/greeting/123?param=test");
assertThat(this.server.getRequestCount()).isEqualTo(0);
}
@Test
void ignoredUriBuilderFactory() throws Exception {
String expectedResponseBody = "hello";
prepareResponse(response -> response.setResponseCode(200).setBody(expectedResponseBody));
prepareResponse(response -> response.code(200).body(expectedResponseBody));
URI dynamicUri = this.server.url("/greeting/123").uri();
UriBuilderFactory factory = new DefaultUriBuilderFactory(this.anotherServer.url("/").toString());
String actualBody = initService().getWithIgnoredUriBuilderFactory(dynamicUri, factory);
assertThat(actualBody).isEqualTo(expectedResponseBody);
assertThat(this.server.takeRequest().getRequestUrl().uri()).isEqualTo(dynamicUri);
assertThat(this.server.takeRequest().getUrl().uri()).isEqualTo(dynamicUri);
assertThat(this.anotherServer.getRequestCount()).isEqualTo(0);
}
@Test
void handleNotFoundException() {
MockResponse response = new MockResponse();
response.setResponseCode(404);
MockResponse response = new MockResponse.Builder().code(404).build();
this.server.enqueue(response);
this.server.enqueue(response);
@ -256,8 +257,10 @@ class WebClientAdapterTests { @@ -256,8 +257,10 @@ class WebClientAdapterTests {
private static MockWebServer anotherServer() {
MockWebServer anotherServer = new MockWebServer();
MockResponse response = new MockResponse();
response.setHeader("Content-Type", "text/plain").setBody(ANOTHER_SERVER_RESPONSE_BODY);
MockResponse response = new MockResponse.Builder()
.setHeader("Content-Type", "text/plain")
.body(ANOTHER_SERVER_RESPONSE_BODY)
.build();
anotherServer.enqueue(response);
return anotherServer;
}
@ -272,10 +275,9 @@ class WebClientAdapterTests { @@ -272,10 +275,9 @@ class WebClientAdapterTests {
return HttpServiceProxyFactory.builderFor(adapter).build().createClient(Service.class);
}
private void prepareResponse(Consumer<MockResponse> consumer) {
MockResponse response = new MockResponse();
consumer.accept(response);
this.server.enqueue(response);
private void prepareResponse(Function<MockResponse.Builder, MockResponse.Builder> f) {
MockResponse.Builder builder = new MockResponse.Builder();
this.server.enqueue(f.apply(builder).build());
}

22
spring-webflux/src/test/java/org/springframework/web/reactive/function/client/support/WebClientProxyRegistryIntegrationTests.java

@ -16,11 +16,9 @@ @@ -16,11 +16,9 @@
package org.springframework.web.reactive.function.client.support;
import java.io.IOException;
import okhttp3.mockwebserver.MockResponse;
import okhttp3.mockwebserver.MockWebServer;
import okhttp3.mockwebserver.RecordedRequest;
import mockwebserver3.MockResponse;
import mockwebserver3.MockWebServer;
import mockwebserver3.RecordedRequest;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.params.ParameterizedTest;
@ -59,8 +57,8 @@ public class WebClientProxyRegistryIntegrationTests { @@ -59,8 +57,8 @@ public class WebClientProxyRegistryIntegrationTests {
}
@AfterEach
void shutdown() throws IOException {
this.server.shutdown();
void shutdown() {
this.server.close();
}
@ -87,7 +85,7 @@ public class WebClientProxyRegistryIntegrationTests { @@ -87,7 +85,7 @@ public class WebClientProxyRegistryIntegrationTests {
assertThat(registry.getClient(GreetingB.class)).isSameAs(greetingB);
for (int i = 0; i < 4; i++) {
this.server.enqueue(new MockResponse().setBody("body"));
this.server.enqueue(new MockResponse.Builder().body("body").build());
}
echoA.handle("a");
@ -95,22 +93,22 @@ public class WebClientProxyRegistryIntegrationTests { @@ -95,22 +93,22 @@ public class WebClientProxyRegistryIntegrationTests {
RecordedRequest request = this.server.takeRequest();
assertThat(request.getMethod()).isEqualTo("GET");
assertThat(request.getPath()).isEqualTo("/echoA?input=a");
assertThat(request.getTarget()).isEqualTo("/echoA?input=a");
request = this.server.takeRequest();
assertThat(request.getMethod()).isEqualTo("GET");
assertThat(request.getPath()).isEqualTo("/echoB?input=b");
assertThat(request.getTarget()).isEqualTo("/echoB?input=b");
greetingA.handle("a");
greetingB.handle("b");
request = this.server.takeRequest();
assertThat(request.getMethod()).isEqualTo("GET");
assertThat(request.getPath()).isEqualTo("/greetingA?input=a");
assertThat(request.getTarget()).isEqualTo("/greetingA?input=a");
request = this.server.takeRequest();
assertThat(request.getMethod()).isEqualTo("GET");
assertThat(request.getPath()).isEqualTo("/greetingB?input=b");
assertThat(request.getTarget()).isEqualTo("/greetingB?input=b");
}

67
spring-webflux/src/test/kotlin/org/springframework/web/reactive/function/client/support/WebClientHttpServiceProxyKotlinTests.kt

@ -16,8 +16,8 @@ @@ -16,8 +16,8 @@
package org.springframework.web.reactive.function.client.support
import kotlinx.coroutines.runBlocking
import okhttp3.mockwebserver.MockResponse
import okhttp3.mockwebserver.MockWebServer
import mockwebserver3.MockResponse
import mockwebserver3.MockWebServer
import org.assertj.core.api.Assertions.assertThat
import org.junit.jupiter.api.AfterEach
import org.junit.jupiter.api.BeforeEach
@ -39,7 +39,6 @@ import reactor.core.publisher.Mono @@ -39,7 +39,6 @@ import reactor.core.publisher.Mono
import reactor.test.StepVerifier
import java.net.URI
import java.time.Duration
import java.util.function.Consumer
/**
* Kotlin integration tests for [HTTP Service proxy][HttpServiceProxyFactory]
@ -58,23 +57,20 @@ class KotlinWebClientHttpServiceGroupAdapterServiceProxyTests { @@ -58,23 +57,20 @@ class KotlinWebClientHttpServiceGroupAdapterServiceProxyTests {
@BeforeEach
fun setUp() {
server = MockWebServer()
server.start()
anotherServer = anotherServer()
anotherServer.start()
}
@AfterEach
fun shutdown() {
server.shutdown()
anotherServer.shutdown()
server.close()
anotherServer.close()
}
@Test
fun greetingSuspending() {
prepareResponse { response: MockResponse ->
response.setHeader(
"Content-Type",
"text/plain"
).setBody("Hello Spring!")
}
prepareResponse { it.setHeader("Content-Type", "text/plain").body("Hello Spring!") }
runBlocking {
val greeting = initHttpService().getGreetingSuspending()
assertThat(greeting).isEqualTo("Hello Spring!")
@ -83,12 +79,7 @@ class KotlinWebClientHttpServiceGroupAdapterServiceProxyTests { @@ -83,12 +79,7 @@ class KotlinWebClientHttpServiceGroupAdapterServiceProxyTests {
@Test
fun greetingMono() {
prepareResponse { response: MockResponse ->
response.setHeader(
"Content-Type",
"text/plain"
).setBody("Hello Spring!")
}
prepareResponse { it.setHeader("Content-Type", "text/plain").body("Hello Spring!") }
StepVerifier.create(initHttpService().getGreetingMono())
.expectNext("Hello Spring!")
.expectComplete()
@ -97,12 +88,7 @@ class KotlinWebClientHttpServiceGroupAdapterServiceProxyTests { @@ -97,12 +88,7 @@ class KotlinWebClientHttpServiceGroupAdapterServiceProxyTests {
@Test
fun greetingBlocking() {
prepareResponse { response: MockResponse ->
response.setHeader(
"Content-Type",
"text/plain"
).setBody("Hello Spring!")
}
prepareResponse { it.setHeader("Content-Type", "text/plain").body("Hello Spring!") }
val greeting = initHttpService().getGreetingBlocking()
assertThat(greeting).isEqualTo("Hello Spring!")
}
@ -117,12 +103,7 @@ class KotlinWebClientHttpServiceGroupAdapterServiceProxyTests { @@ -117,12 +103,7 @@ class KotlinWebClientHttpServiceGroupAdapterServiceProxyTests {
next.exchange(request)
}
.build()
prepareResponse { response: MockResponse ->
response.setHeader(
"Content-Type",
"text/plain"
).setBody("Hello Spring!")
}
prepareResponse { it.setHeader("Content-Type", "text/plain").body("Hello Spring!") }
val service = initHttpService(webClient)
runBlocking {
val greeting = service.getGreetingSuspendingWithAttribute("myAttributeValue")
@ -134,9 +115,7 @@ class KotlinWebClientHttpServiceGroupAdapterServiceProxyTests { @@ -134,9 +115,7 @@ class KotlinWebClientHttpServiceGroupAdapterServiceProxyTests {
@Test
@Throws(InterruptedException::class)
fun getWithFactoryPathVariableAndRequestParam() {
prepareResponse { response: MockResponse ->
response.setHeader("Content-Type", "text/plain").setBody("Hello Spring!")
}
prepareResponse { it.setHeader("Content-Type", "text/plain").body("Hello Spring!") }
val factory: UriBuilderFactory = DefaultUriBuilderFactory(anotherServer.url("/").toString())
val actualResponse: ResponseEntity<String> =
@ -146,17 +125,16 @@ class KotlinWebClientHttpServiceGroupAdapterServiceProxyTests { @@ -146,17 +125,16 @@ class KotlinWebClientHttpServiceGroupAdapterServiceProxyTests {
assertThat(actualResponse.statusCode).isEqualTo(HttpStatus.OK)
assertThat(actualResponse.body).isEqualTo("Hello Spring 2!")
assertThat(request.method).isEqualTo("GET")
assertThat(request.path).isEqualTo("/greeting/123?param=test")
assertThat(request.target).isEqualTo("/greeting/123?param=test")
assertThat(server.requestCount).isEqualTo(0)
}
@Test
@Throws(InterruptedException::class)
fun getWithIgnoredUriBuilderFactory() {
prepareResponse { response: MockResponse ->
response.setHeader("Content-Type", "text/plain").setBody("Hello Spring!")
}
val dynamicUri = server.url("/greeting/123").uri()
prepareResponse {
it.setHeader("Content-Type", "text/plain").body("Hello Spring!") }
val dynamicUri = server.url("/greeting/123").toUri()
val factory: UriBuilderFactory = DefaultUriBuilderFactory(anotherServer.url("/").toString())
val actualResponse: ResponseEntity<String> =
@ -166,7 +144,7 @@ class KotlinWebClientHttpServiceGroupAdapterServiceProxyTests { @@ -166,7 +144,7 @@ class KotlinWebClientHttpServiceGroupAdapterServiceProxyTests {
assertThat(actualResponse.statusCode).isEqualTo(HttpStatus.OK)
assertThat(actualResponse.body).isEqualTo("Hello Spring!")
assertThat(request.method).isEqualTo("GET")
assertThat(request.path).isEqualTo("/greeting/123")
assertThat(request.target).isEqualTo("/greeting/123")
assertThat(anotherServer.requestCount).isEqualTo(0)
}
@ -181,16 +159,17 @@ class KotlinWebClientHttpServiceGroupAdapterServiceProxyTests { @@ -181,16 +159,17 @@ class KotlinWebClientHttpServiceGroupAdapterServiceProxyTests {
return HttpServiceProxyFactory.builderFor(adapter).build().createClient()
}
private fun prepareResponse(consumer: Consumer<MockResponse>) {
val response = MockResponse()
consumer.accept(response)
server.enqueue(response)
private fun prepareResponse(f: (MockResponse.Builder) -> MockResponse.Builder) {
val builder = MockResponse.Builder()
server.enqueue(f.invoke(builder).build())
}
private fun anotherServer(): MockWebServer {
val anotherServer = MockWebServer()
val response = MockResponse()
response.setHeader("Content-Type", "text/plain").setBody("Hello Spring 2!")
val response = MockResponse.Builder()
.setHeader("Content-Type", "text/plain")
.body("Hello Spring 2!")
.build()
anotherServer.enqueue(response)
return anotherServer
}

Loading…
Cancel
Save