Allow responses with non-standard status codes to be documented
Fixes gh-639
This commit is contained in:
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2014-2015 the original author or authors.
|
* Copyright 2014-2019 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -30,10 +30,18 @@ public interface OperationResponse {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the status of the response.
|
* Returns the status of the response.
|
||||||
* @return the status
|
* @return the status or {@code null} if the status is unknown to {@link HttpStatus}
|
||||||
*/
|
*/
|
||||||
HttpStatus getStatus();
|
HttpStatus getStatus();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the status code of the response.
|
||||||
|
* @return the status code
|
||||||
|
*/
|
||||||
|
default int getStatusCode() {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the headers in the response.
|
* Returns the headers in the response.
|
||||||
* @return the headers
|
* @return the headers
|
||||||
|
|||||||
@@ -34,8 +34,14 @@ public class OperationResponseFactory {
|
|||||||
* @param headers the request's headers
|
* @param headers the request's headers
|
||||||
* @param content the content of the request
|
* @param content the content of the request
|
||||||
* @return the {@code OperationResponse}
|
* @return the {@code OperationResponse}
|
||||||
|
* @deprecated since 2.0.4 in favor of {@link #create(int, HttpHeaders, byte[])}
|
||||||
*/
|
*/
|
||||||
|
@Deprecated
|
||||||
public OperationResponse create(HttpStatus status, HttpHeaders headers, byte[] content) {
|
public OperationResponse create(HttpStatus status, HttpHeaders headers, byte[] content) {
|
||||||
|
return this.create(status.value(), headers, content);
|
||||||
|
}
|
||||||
|
|
||||||
|
public OperationResponse create(int status, HttpHeaders headers, byte[] content) {
|
||||||
return new StandardOperationResponse(status, augmentHeaders(headers, content), content);
|
return new StandardOperationResponse(status, augmentHeaders(headers, content), content);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -49,8 +55,8 @@ public class OperationResponseFactory {
|
|||||||
* @return the new response with the new content
|
* @return the new response with the new content
|
||||||
*/
|
*/
|
||||||
public OperationResponse createFrom(OperationResponse original, byte[] newContent) {
|
public OperationResponse createFrom(OperationResponse original, byte[] newContent) {
|
||||||
return new StandardOperationResponse(original.getStatus(), getUpdatedHeaders(original.getHeaders(), newContent),
|
return new StandardOperationResponse(original.getStatusCode(),
|
||||||
newContent);
|
getUpdatedHeaders(original.getHeaders(), newContent), newContent);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -61,7 +67,7 @@ public class OperationResponseFactory {
|
|||||||
* @return the new response with the new headers
|
* @return the new response with the new headers
|
||||||
*/
|
*/
|
||||||
public OperationResponse createFrom(OperationResponse original, HttpHeaders newHeaders) {
|
public OperationResponse createFrom(OperationResponse original, HttpHeaders newHeaders) {
|
||||||
return new StandardOperationResponse(original.getStatus(), newHeaders, original.getContent());
|
return new StandardOperationResponse(original.getStatusCode(), newHeaders, original.getContent());
|
||||||
}
|
}
|
||||||
|
|
||||||
private HttpHeaders augmentHeaders(HttpHeaders originalHeaders, byte[] content) {
|
private HttpHeaders augmentHeaders(HttpHeaders originalHeaders, byte[] content) {
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ import org.springframework.http.HttpStatus;
|
|||||||
*/
|
*/
|
||||||
class StandardOperationResponse extends AbstractOperationMessage implements OperationResponse {
|
class StandardOperationResponse extends AbstractOperationMessage implements OperationResponse {
|
||||||
|
|
||||||
private final HttpStatus status;
|
private final int status;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new response with the given {@code status}, {@code headers}, and
|
* Creates a new response with the given {@code status}, {@code headers}, and
|
||||||
@@ -35,13 +35,18 @@ class StandardOperationResponse extends AbstractOperationMessage implements Oper
|
|||||||
* @param headers the headers of the response
|
* @param headers the headers of the response
|
||||||
* @param content the content of the response
|
* @param content the content of the response
|
||||||
*/
|
*/
|
||||||
StandardOperationResponse(HttpStatus status, HttpHeaders headers, byte[] content) {
|
StandardOperationResponse(int status, HttpHeaders headers, byte[] content) {
|
||||||
super(content, headers);
|
super(content, headers);
|
||||||
this.status = status;
|
this.status = status;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public HttpStatus getStatus() {
|
public HttpStatus getStatus() {
|
||||||
|
return HttpStatus.resolve(this.status);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getStatusCode() {
|
||||||
return this.status;
|
return this.status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -141,7 +141,7 @@ public class UriModifyingOperationPreprocessor implements OperationPreprocessor
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public OperationResponse preprocess(OperationResponse response) {
|
public OperationResponse preprocess(OperationResponse response) {
|
||||||
return this.contentModifyingDelegate.preprocess(new OperationResponseFactory().create(response.getStatus(),
|
return this.contentModifyingDelegate.preprocess(new OperationResponseFactory().create(response.getStatusCode(),
|
||||||
modify(response.getHeaders()), response.getContent()));
|
modify(response.getHeaders()), response.getContent()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -69,7 +69,7 @@ public class RestDocumentationGeneratorTests {
|
|||||||
private final OperationRequest operationRequest = new OperationRequestFactory()
|
private final OperationRequest operationRequest = new OperationRequestFactory()
|
||||||
.create(URI.create("http://localhost:8080"), null, null, new HttpHeaders(), null, null);
|
.create(URI.create("http://localhost:8080"), null, null, new HttpHeaders(), null, null);
|
||||||
|
|
||||||
private final OperationResponse operationResponse = new OperationResponseFactory().create(null, null, null);
|
private final OperationResponse operationResponse = new OperationResponseFactory().create(0, null, null);
|
||||||
|
|
||||||
private final Snippet snippet = mock(Snippet.class);
|
private final Snippet snippet = mock(Snippet.class);
|
||||||
|
|
||||||
@@ -197,7 +197,7 @@ public class RestDocumentationGeneratorTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static OperationResponse createResponse() {
|
private static OperationResponse createResponse() {
|
||||||
return new OperationResponseFactory().create(null, null, null);
|
return new OperationResponseFactory().create(0, null, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -217,7 +217,7 @@ public class RestDocumentationConfigurerTests {
|
|||||||
.get(RestDocumentationGenerator.ATTRIBUTE_NAME_DEFAULT_OPERATION_RESPONSE_PREPROCESSOR);
|
.get(RestDocumentationGenerator.ATTRIBUTE_NAME_DEFAULT_OPERATION_RESPONSE_PREPROCESSOR);
|
||||||
HttpHeaders headers = new HttpHeaders();
|
HttpHeaders headers = new HttpHeaders();
|
||||||
headers.add("Foo", "value");
|
headers.add("Foo", "value");
|
||||||
OperationResponse response = new OperationResponseFactory().create(HttpStatus.OK, headers, null);
|
OperationResponse response = new OperationResponseFactory().create(HttpStatus.OK.value(), headers, null);
|
||||||
assertThat(preprocessor.preprocess(response).getHeaders()).doesNotContainKey("Foo");
|
assertThat(preprocessor.preprocess(response).getHeaders()).doesNotContainKey("Foo");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -49,7 +49,7 @@ public class ContentTypeLinkExtractorTests {
|
|||||||
public void extractionFailsWithNullContentType() throws IOException {
|
public void extractionFailsWithNullContentType() throws IOException {
|
||||||
this.thrown.expect(IllegalStateException.class);
|
this.thrown.expect(IllegalStateException.class);
|
||||||
new ContentTypeLinkExtractor()
|
new ContentTypeLinkExtractor()
|
||||||
.extractLinks(this.responseFactory.create(HttpStatus.OK, new HttpHeaders(), null));
|
.extractLinks(this.responseFactory.create(HttpStatus.OK.value(), new HttpHeaders(), null));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -59,7 +59,7 @@ public class ContentTypeLinkExtractorTests {
|
|||||||
extractors.put(MediaType.APPLICATION_JSON, extractor);
|
extractors.put(MediaType.APPLICATION_JSON, extractor);
|
||||||
HttpHeaders httpHeaders = new HttpHeaders();
|
HttpHeaders httpHeaders = new HttpHeaders();
|
||||||
httpHeaders.setContentType(MediaType.APPLICATION_JSON);
|
httpHeaders.setContentType(MediaType.APPLICATION_JSON);
|
||||||
OperationResponse response = this.responseFactory.create(HttpStatus.OK, httpHeaders, null);
|
OperationResponse response = this.responseFactory.create(HttpStatus.OK.value(), httpHeaders, null);
|
||||||
new ContentTypeLinkExtractor(extractors).extractLinks(response);
|
new ContentTypeLinkExtractor(extractors).extractLinks(response);
|
||||||
verify(extractor).extractLinks(response);
|
verify(extractor).extractLinks(response);
|
||||||
}
|
}
|
||||||
@@ -71,7 +71,7 @@ public class ContentTypeLinkExtractorTests {
|
|||||||
extractors.put(MediaType.APPLICATION_JSON, extractor);
|
extractors.put(MediaType.APPLICATION_JSON, extractor);
|
||||||
HttpHeaders httpHeaders = new HttpHeaders();
|
HttpHeaders httpHeaders = new HttpHeaders();
|
||||||
httpHeaders.setContentType(MediaType.parseMediaType("application/json;foo=bar"));
|
httpHeaders.setContentType(MediaType.parseMediaType("application/json;foo=bar"));
|
||||||
OperationResponse response = this.responseFactory.create(HttpStatus.OK, httpHeaders, null);
|
OperationResponse response = this.responseFactory.create(HttpStatus.OK.value(), httpHeaders, null);
|
||||||
new ContentTypeLinkExtractor(extractors).extractLinks(response);
|
new ContentTypeLinkExtractor(extractors).extractLinks(response);
|
||||||
verify(extractor).extractLinks(response);
|
verify(extractor).extractLinks(response);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -106,7 +106,7 @@ public class LinkExtractorsPayloadTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private OperationResponse createResponse(String contentName) throws IOException {
|
private OperationResponse createResponse(String contentName) throws IOException {
|
||||||
return this.responseFactory.create(HttpStatus.OK, null,
|
return this.responseFactory.create(HttpStatus.OK.value(), null,
|
||||||
FileCopyUtils.copyToByteArray(getPayloadFile(contentName)));
|
FileCopyUtils.copyToByteArray(getPayloadFile(contentName)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -67,7 +67,7 @@ public class ContentModifyingOperationPreprocessorTests {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void modifyResponseContent() {
|
public void modifyResponseContent() {
|
||||||
OperationResponse response = this.responseFactory.create(HttpStatus.OK, new HttpHeaders(),
|
OperationResponse response = this.responseFactory.create(HttpStatus.OK.value(), new HttpHeaders(),
|
||||||
"content".getBytes());
|
"content".getBytes());
|
||||||
OperationResponse preprocessed = this.preprocessor.preprocess(response);
|
OperationResponse preprocessed = this.preprocessor.preprocess(response);
|
||||||
assertThat(preprocessed.getContent()).isEqualTo("modified".getBytes());
|
assertThat(preprocessed.getContent()).isEqualTo("modified".getBytes());
|
||||||
|
|||||||
@@ -87,7 +87,7 @@ public class HeaderRemovingOperationPreprocessorTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private OperationResponse createResponse(String... extraHeaders) {
|
private OperationResponse createResponse(String... extraHeaders) {
|
||||||
return this.responseFactory.create(HttpStatus.OK, getHttpHeaders(extraHeaders), new byte[0]);
|
return this.responseFactory.create(HttpStatus.OK.value(), getHttpHeaders(extraHeaders), new byte[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
private HttpHeaders getHttpHeaders(String... extraHeaders) {
|
private HttpHeaders getHttpHeaders(String... extraHeaders) {
|
||||||
|
|||||||
@@ -321,13 +321,13 @@ public class UriModifyingOperationPreprocessorTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private OperationResponse createResponseWithContent(String content) {
|
private OperationResponse createResponseWithContent(String content) {
|
||||||
return this.responseFactory.create(HttpStatus.OK, new HttpHeaders(), content.getBytes());
|
return this.responseFactory.create(HttpStatus.OK.value(), new HttpHeaders(), content.getBytes());
|
||||||
}
|
}
|
||||||
|
|
||||||
private OperationResponse createResponseWithHeader(String name, String value) {
|
private OperationResponse createResponseWithHeader(String name, String value) {
|
||||||
HttpHeaders headers = new HttpHeaders();
|
HttpHeaders headers = new HttpHeaders();
|
||||||
headers.add(name, value);
|
headers.add(name, value);
|
||||||
return this.responseFactory.create(HttpStatus.OK, headers, new byte[0]);
|
return this.responseFactory.create(HttpStatus.OK.value(), headers, new byte[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -261,7 +261,7 @@ public class OperationBuilder extends OperationTestRule {
|
|||||||
*/
|
*/
|
||||||
public final class OperationResponseBuilder {
|
public final class OperationResponseBuilder {
|
||||||
|
|
||||||
private HttpStatus status = HttpStatus.OK;
|
private int status = HttpStatus.OK.value();
|
||||||
|
|
||||||
private HttpHeaders headers = new HttpHeaders();
|
private HttpHeaders headers = new HttpHeaders();
|
||||||
|
|
||||||
@@ -272,7 +272,7 @@ public class OperationBuilder extends OperationTestRule {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public OperationResponseBuilder status(int status) {
|
public OperationResponseBuilder status(int status) {
|
||||||
this.status = HttpStatus.valueOf(status);
|
this.status = status;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -19,7 +19,6 @@ package org.springframework.restdocs.mockmvc;
|
|||||||
import javax.servlet.http.Cookie;
|
import javax.servlet.http.Cookie;
|
||||||
|
|
||||||
import org.springframework.http.HttpHeaders;
|
import org.springframework.http.HttpHeaders;
|
||||||
import org.springframework.http.HttpStatus;
|
|
||||||
import org.springframework.mock.web.MockHttpServletResponse;
|
import org.springframework.mock.web.MockHttpServletResponse;
|
||||||
import org.springframework.restdocs.operation.OperationResponse;
|
import org.springframework.restdocs.operation.OperationResponse;
|
||||||
import org.springframework.restdocs.operation.OperationResponseFactory;
|
import org.springframework.restdocs.operation.OperationResponseFactory;
|
||||||
@@ -36,8 +35,8 @@ class MockMvcResponseConverter implements ResponseConverter<MockHttpServletRespo
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public OperationResponse convert(MockHttpServletResponse mockResponse) {
|
public OperationResponse convert(MockHttpServletResponse mockResponse) {
|
||||||
return new OperationResponseFactory().create(HttpStatus.valueOf(mockResponse.getStatus()),
|
return new OperationResponseFactory().create(mockResponse.getStatus(), extractHeaders(mockResponse),
|
||||||
extractHeaders(mockResponse), mockResponse.getContentAsByteArray());
|
mockResponse.getContentAsByteArray());
|
||||||
}
|
}
|
||||||
|
|
||||||
private HttpHeaders extractHeaders(MockHttpServletResponse response) {
|
private HttpHeaders extractHeaders(MockHttpServletResponse response) {
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2014-2018 the original author or authors.
|
* Copyright 2014-2019 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -61,4 +61,13 @@ public class MockMvcResponseConverterTests {
|
|||||||
Collections.singletonList("name=value; Domain=localhost; HttpOnly"));
|
Collections.singletonList("name=value; Domain=localhost; HttpOnly"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void responseWithCustomStatus() {
|
||||||
|
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||||
|
response.setStatus(600);
|
||||||
|
OperationResponse operationResponse = this.factory.convert(response);
|
||||||
|
assertThat(operationResponse.getStatus()).isNull();
|
||||||
|
assertThat(operationResponse.getStatusCode()).isEqualTo(600);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,7 +20,6 @@ import io.restassured.http.Header;
|
|||||||
import io.restassured.response.Response;
|
import io.restassured.response.Response;
|
||||||
|
|
||||||
import org.springframework.http.HttpHeaders;
|
import org.springframework.http.HttpHeaders;
|
||||||
import org.springframework.http.HttpStatus;
|
|
||||||
import org.springframework.restdocs.operation.OperationResponse;
|
import org.springframework.restdocs.operation.OperationResponse;
|
||||||
import org.springframework.restdocs.operation.OperationResponseFactory;
|
import org.springframework.restdocs.operation.OperationResponseFactory;
|
||||||
import org.springframework.restdocs.operation.ResponseConverter;
|
import org.springframework.restdocs.operation.ResponseConverter;
|
||||||
@@ -35,8 +34,8 @@ class RestAssuredResponseConverter implements ResponseConverter<Response> {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public OperationResponse convert(Response response) {
|
public OperationResponse convert(Response response) {
|
||||||
return new OperationResponseFactory().create(HttpStatus.valueOf(response.getStatusCode()),
|
return new OperationResponseFactory().create(response.getStatusCode(), extractHeaders(response),
|
||||||
extractHeaders(response), extractContent(response));
|
extractContent(response));
|
||||||
}
|
}
|
||||||
|
|
||||||
private HttpHeaders extractHeaders(Response response) {
|
private HttpHeaders extractHeaders(Response response) {
|
||||||
|
|||||||
@@ -0,0 +1,52 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2014-2019 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.restdocs.restassured3;
|
||||||
|
|
||||||
|
import io.restassured.http.Headers;
|
||||||
|
import io.restassured.response.Response;
|
||||||
|
import io.restassured.response.ResponseBody;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import org.springframework.restdocs.operation.OperationResponse;
|
||||||
|
|
||||||
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
import static org.mockito.BDDMockito.given;
|
||||||
|
import static org.mockito.Mockito.mock;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests for {@link RestAssuredResponseConverter}.
|
||||||
|
*
|
||||||
|
* @author Andy Wilkinson
|
||||||
|
*/
|
||||||
|
public class RestAssuredResponseConverterTests {
|
||||||
|
|
||||||
|
private final RestAssuredResponseConverter converter = new RestAssuredResponseConverter();
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void responseWithCustomStatus() {
|
||||||
|
Response response = mock(Response.class);
|
||||||
|
given(response.getStatusCode()).willReturn(600);
|
||||||
|
given(response.getHeaders()).willReturn(new Headers());
|
||||||
|
ResponseBody<?> body = mock(ResponseBody.class);
|
||||||
|
given(response.getBody()).willReturn(body);
|
||||||
|
given(body.asByteArray()).willReturn(new byte[0]);
|
||||||
|
OperationResponse operationResponse = this.converter.convert(response);
|
||||||
|
assertThat(operationResponse.getStatus()).isNull();
|
||||||
|
assertThat(operationResponse.getStatusCode()).isEqualTo(600);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -36,7 +36,7 @@ class WebTestClientResponseConverter implements ResponseConverter<ExchangeResult
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public OperationResponse convert(ExchangeResult result) {
|
public OperationResponse convert(ExchangeResult result) {
|
||||||
return new OperationResponseFactory().create(result.getStatus(), extractHeaders(result),
|
return new OperationResponseFactory().create(result.getStatus().value(), extractHeaders(result),
|
||||||
result.getResponseBodyContent());
|
result.getResponseBodyContent());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user