Browse Source

Extract Mock HTTP client requests and responses

This commit extracts Mock HTTP client request and response for the
imperative variant. These are made available in the testFixtures
configuration for shared usage.
pull/29136/head
Brian Clozel 4 years ago
parent
commit
f9dcd428ae
  1. 133
      spring-web/src/test/java/org/springframework/http/client/InterceptingClientHttpRequestFactoryTests.java
  2. 154
      spring-web/src/testFixtures/java/org/springframework/web/testfixture/http/client/MockClientHttpRequest.java
  3. 99
      spring-web/src/testFixtures/java/org/springframework/web/testfixture/http/client/MockClientHttpResponse.java
  4. 9
      spring-web/src/testFixtures/java/org/springframework/web/testfixture/http/client/package-info.java
  5. 9
      spring-web/src/testFixtures/java/org/springframework/web/testfixture/http/client/reactive/package-info.java

133
spring-web/src/test/java/org/springframework/http/client/InterceptingClientHttpRequestFactoryTests.java

@ -16,23 +16,21 @@ @@ -16,23 +16,21 @@
package org.springframework.http.client;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URI;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.HttpRequest;
import org.springframework.http.HttpStatus;
import org.springframework.http.client.support.HttpRequestWrapper;
import org.springframework.web.testfixture.http.client.MockClientHttpRequest;
import org.springframework.web.testfixture.http.client.MockClientHttpResponse;
import static org.assertj.core.api.Assertions.assertThat;
@ -44,12 +42,16 @@ class InterceptingClientHttpRequestFactoryTests { @@ -44,12 +42,16 @@ class InterceptingClientHttpRequestFactoryTests {
private RequestFactoryMock requestFactoryMock = new RequestFactoryMock();
private RequestMock requestMock = new RequestMock();
private MockClientHttpRequest requestMock = new MockClientHttpRequest();
private ResponseMock responseMock = new ResponseMock();
private MockClientHttpResponse responseMock = new MockClientHttpResponse();
private InterceptingClientHttpRequestFactory requestFactory;
@BeforeEach
void beforeEach() {
this.requestMock.setResponse(this.responseMock);
}
@Test
void basic() throws Exception {
@ -65,7 +67,7 @@ class InterceptingClientHttpRequestFactoryTests { @@ -65,7 +67,7 @@ class InterceptingClientHttpRequestFactoryTests {
assertThat(((NoOpInterceptor) interceptors.get(0)).invoked).isTrue();
assertThat(((NoOpInterceptor) interceptors.get(1)).invoked).isTrue();
assertThat(((NoOpInterceptor) interceptors.get(2)).invoked).isTrue();
assertThat(requestMock.executed).isTrue();
assertThat(requestMock.isExecuted()).isTrue();
assertThat(response).isSameAs(responseMock);
}
@ -81,7 +83,7 @@ class InterceptingClientHttpRequestFactoryTests { @@ -81,7 +83,7 @@ class InterceptingClientHttpRequestFactoryTests {
ClientHttpResponse response = request.execute();
assertThat(((NoOpInterceptor) interceptors.get(1)).invoked).isFalse();
assertThat(requestMock.executed).isFalse();
assertThat(requestMock.isExecuted()).isFalse();
assertThat(response).isSameAs(responseMock);
}
@ -92,19 +94,19 @@ class InterceptingClientHttpRequestFactoryTests { @@ -92,19 +94,19 @@ class InterceptingClientHttpRequestFactoryTests {
final String otherValue = "Baz";
ClientHttpRequestInterceptor interceptor = (request, body, execution) -> {
HttpRequestWrapper wrapper = new HttpRequestWrapper(request);
wrapper.getHeaders().add(headerName, otherValue);
return execution.execute(wrapper, body);
};
HttpRequestWrapper wrapper = new HttpRequestWrapper(request);
wrapper.getHeaders().add(headerName, otherValue);
return execution.execute(wrapper, body);
};
requestMock = new RequestMock() {
requestMock = new MockClientHttpRequest() {
@Override
public ClientHttpResponse execute() throws IOException {
protected ClientHttpResponse executeInternal() throws IOException {
List<String> headerValues = getHeaders().get(headerName);
assertThat(headerValues.size()).isEqualTo(2);
assertThat(headerValues.get(0)).isEqualTo(headerValue);
assertThat(headerValues.get(1)).isEqualTo(otherValue);
return super.execute();
return responseMock;
}
};
requestMock.getHeaders().add(headerName, headerValue);
@ -177,7 +179,7 @@ class InterceptingClientHttpRequestFactoryTests { @@ -177,7 +179,7 @@ class InterceptingClientHttpRequestFactoryTests {
ClientHttpRequest request = requestFactory.createRequest(new URI("https://example.com"), HttpMethod.GET);
request.execute();
assertThat(Arrays.equals(changedBody, requestMock.body.toByteArray())).isTrue();
assertThat(Arrays.equals(changedBody, requestMock.getBodyAsBytes())).isTrue();
}
@ -205,101 +207,4 @@ class InterceptingClientHttpRequestFactoryTests { @@ -205,101 +207,4 @@ class InterceptingClientHttpRequestFactoryTests {
}
private class RequestMock implements ClientHttpRequest {
private URI uri;
private HttpMethod method;
private HttpHeaders headers = new HttpHeaders();
private ByteArrayOutputStream body = new ByteArrayOutputStream();
private boolean executed = false;
private RequestMock() {
}
@Override
public URI getURI() {
return uri;
}
public void setURI(URI uri) {
this.uri = uri;
}
@Override
public HttpMethod getMethod() {
return method;
}
@Override
@Deprecated
public String getMethodValue() {
return method.name();
}
public void setMethod(HttpMethod method) {
this.method = method;
}
@Override
public HttpHeaders getHeaders() {
return headers;
}
@Override
public OutputStream getBody() throws IOException {
return body;
}
@Override
public ClientHttpResponse execute() throws IOException {
executed = true;
return responseMock;
}
}
private static class ResponseMock implements ClientHttpResponse {
private HttpStatus statusCode = HttpStatus.OK;
private String statusText = "";
private HttpHeaders headers = new HttpHeaders();
@Override
public HttpStatus getStatusCode() throws IOException {
return statusCode;
}
@Override
@SuppressWarnings("deprecation")
public int getRawStatusCode() throws IOException {
return statusCode.value();
}
@Override
public String getStatusText() throws IOException {
return statusText;
}
@Override
public HttpHeaders getHeaders() {
return headers;
}
@Override
public InputStream getBody() throws IOException {
return null;
}
@Override
public void close() {
}
}
}

154
spring-web/src/testFixtures/java/org/springframework/web/testfixture/http/client/MockClientHttpRequest.java

@ -0,0 +1,154 @@ @@ -0,0 +1,154 @@
/*
* Copyright 2002-2022 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.web.testfixture.http.client;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.net.URI;
import java.net.URISyntaxException;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.client.ClientHttpRequest;
import org.springframework.http.client.ClientHttpResponse;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.StreamUtils;
import org.springframework.web.util.UriComponentsBuilder;
/**
* Mock implementation of {@link ClientHttpRequest}.
*
* @author Brian Clozel
* @author Rossen Stoyanchev
*/
public class MockClientHttpRequest implements ClientHttpRequest {
private static final Charset DEFAULT_CHARSET = StandardCharsets.UTF_8;
private final HttpHeaders headers = new HttpHeaders();
private HttpMethod httpMethod;
private URI uri;
private final ByteArrayOutputStream body = new ByteArrayOutputStream(1024);
@Nullable
private ClientHttpResponse clientHttpResponse;
private boolean executed = false;
public MockClientHttpRequest() {
this.httpMethod = HttpMethod.GET;
try {
this.uri = new URI("/");
}
catch (URISyntaxException ex) {
throw new IllegalStateException(ex);
}
}
public MockClientHttpRequest(HttpMethod httpMethod, String urlTemplate, Object... vars) {
this.httpMethod = httpMethod;
this.uri = UriComponentsBuilder.fromUriString(urlTemplate).buildAndExpand(vars).encode().toUri();
}
@Override
public HttpHeaders getHeaders() {
return this.headers;
}
@Override
public OutputStream getBody() throws IOException {
return this.body;
}
public byte[] getBodyAsBytes() {
return this.body.toByteArray();
}
public String getBodyAsString() {
return getBodyAsString(DEFAULT_CHARSET);
}
public String getBodyAsString(Charset charset) {
return StreamUtils.copyToString(this.body, charset);
}
public void setMethod(HttpMethod httpMethod) {
this.httpMethod = httpMethod;
}
@Override
public HttpMethod getMethod() {
return this.httpMethod;
}
@Override
@Deprecated
public String getMethodValue() {
return this.httpMethod.name();
}
public void setURI(URI uri) {
this.uri = uri;
}
@Override
public URI getURI() {
return this.uri;
}
public void setResponse(ClientHttpResponse clientHttpResponse) {
this.clientHttpResponse = clientHttpResponse;
}
public boolean isExecuted() {
return this.executed;
}
@Override
public final ClientHttpResponse execute() throws IOException {
this.executed = true;
return executeInternal();
}
protected ClientHttpResponse executeInternal() throws IOException {
Assert.state(this.clientHttpResponse != null, "No ClientHttpResponse");
return this.clientHttpResponse;
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append(this.httpMethod);
sb.append(' ').append(this.uri);
if (!getHeaders().isEmpty()) {
sb.append(", headers: ").append(getHeaders());
}
if (sb.length() == 0) {
sb.append("Not yet initialized");
}
return sb.toString();
}
}

99
spring-web/src/testFixtures/java/org/springframework/web/testfixture/http/client/MockClientHttpResponse.java

@ -0,0 +1,99 @@ @@ -0,0 +1,99 @@
/*
* Copyright 2002-2022 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.web.testfixture.http.client;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.client.ClientHttpResponse;
import org.springframework.util.Assert;
/**
* Mock implementation of {@link ClientHttpResponse}.
*
* @author Rossen Stoyanchev
* @author Brian Clozel
*/
public class MockClientHttpResponse implements ClientHttpResponse {
private final HttpHeaders headers = new HttpHeaders();
private final HttpStatus status;
private InputStream body;
public MockClientHttpResponse() {
this.status = HttpStatus.OK;
}
public MockClientHttpResponse(HttpStatus statusCode) {
Assert.notNull(statusCode, "HttpStatus is required");
this.status = statusCode;
}
@Override
public HttpStatus getStatusCode() throws IOException {
return this.status;
}
@Override
@SuppressWarnings("deprecation")
public int getRawStatusCode() throws IOException {
return this.status.value();
}
@Override
public String getStatusText() throws IOException {
return this.status.getReasonPhrase();
}
@Override
public HttpHeaders getHeaders() {
return this.headers;
}
@Override
public InputStream getBody() throws IOException {
return this.body;
}
public void setBody(byte[] body) {
Assert.notNull(body, "body is required");
this.body = new ByteArrayInputStream(body);
}
public void setBody(String body) {
Assert.notNull(body, "body is required");
this.body = new ByteArrayInputStream(body.getBytes(StandardCharsets.UTF_8));
}
@Override
public void close() {
try {
getBody().close();
}
catch (IOException ex) {
// ignore
}
}
}

9
spring-web/src/testFixtures/java/org/springframework/web/testfixture/http/client/package-info.java

@ -0,0 +1,9 @@ @@ -0,0 +1,9 @@
/**
* Contains mock request and response types for the imperative HTTP client
*/
@NonNullApi
@NonNullFields
package org.springframework.web.testfixture.http.client;
import org.springframework.lang.NonNullApi;
import org.springframework.lang.NonNullFields;

9
spring-web/src/testFixtures/java/org/springframework/web/testfixture/http/client/reactive/package-info.java

@ -0,0 +1,9 @@ @@ -0,0 +1,9 @@
/**
* Contains mock request and response types for the reactive HTTP client
*/
@NonNullApi
@NonNullFields
package org.springframework.web.testfixture.http.client.reactive;
import org.springframework.lang.NonNullApi;
import org.springframework.lang.NonNullFields;
Loading…
Cancel
Save