Skip to content

Commit 3597ebc

Browse files
committed
Allow responses with non-standard status codes to be documented
Fixes gh-639
1 parent d586d9f commit 3597ebc

File tree

17 files changed

+107
-29
lines changed

17 files changed

+107
-29
lines changed

spring-restdocs-core/src/main/java/org/springframework/restdocs/operation/OperationResponse.java

+10-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2014-2015 the original author or authors.
2+
* Copyright 2014-2019 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -30,10 +30,18 @@ public interface OperationResponse {
3030

3131
/**
3232
* Returns the status of the response.
33-
* @return the status
33+
* @return the status or {@code null} if the status is unknown to {@link HttpStatus}
3434
*/
3535
HttpStatus getStatus();
3636

37+
/**
38+
* Returns the status code of the response.
39+
* @return the status code
40+
*/
41+
default int getStatusCode() {
42+
throw new UnsupportedOperationException();
43+
}
44+
3745
/**
3846
* Returns the headers in the response.
3947
* @return the headers

spring-restdocs-core/src/main/java/org/springframework/restdocs/operation/OperationResponseFactory.java

+9-3
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,14 @@ public class OperationResponseFactory {
3434
* @param headers the request's headers
3535
* @param content the content of the request
3636
* @return the {@code OperationResponse}
37+
* @deprecated since 2.0.4 in favor of {@link #create(int, HttpHeaders, byte[])}
3738
*/
39+
@Deprecated
3840
public OperationResponse create(HttpStatus status, HttpHeaders headers, byte[] content) {
41+
return this.create(status.value(), headers, content);
42+
}
43+
44+
public OperationResponse create(int status, HttpHeaders headers, byte[] content) {
3945
return new StandardOperationResponse(status, augmentHeaders(headers, content), content);
4046
}
4147

@@ -49,8 +55,8 @@ public OperationResponse create(HttpStatus status, HttpHeaders headers, byte[] c
4955
* @return the new response with the new content
5056
*/
5157
public OperationResponse createFrom(OperationResponse original, byte[] newContent) {
52-
return new StandardOperationResponse(original.getStatus(), getUpdatedHeaders(original.getHeaders(), newContent),
53-
newContent);
58+
return new StandardOperationResponse(original.getStatusCode(),
59+
getUpdatedHeaders(original.getHeaders(), newContent), newContent);
5460
}
5561

5662
/**
@@ -61,7 +67,7 @@ public OperationResponse createFrom(OperationResponse original, byte[] newConten
6167
* @return the new response with the new headers
6268
*/
6369
public OperationResponse createFrom(OperationResponse original, HttpHeaders newHeaders) {
64-
return new StandardOperationResponse(original.getStatus(), newHeaders, original.getContent());
70+
return new StandardOperationResponse(original.getStatusCode(), newHeaders, original.getContent());
6571
}
6672

6773
private HttpHeaders augmentHeaders(HttpHeaders originalHeaders, byte[] content) {

spring-restdocs-core/src/main/java/org/springframework/restdocs/operation/StandardOperationResponse.java

+7-2
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@
2626
*/
2727
class StandardOperationResponse extends AbstractOperationMessage implements OperationResponse {
2828

29-
private final HttpStatus status;
29+
private final int status;
3030

3131
/**
3232
* Creates a new response with the given {@code status}, {@code headers}, and
@@ -35,13 +35,18 @@ class StandardOperationResponse extends AbstractOperationMessage implements Oper
3535
* @param headers the headers of the response
3636
* @param content the content of the response
3737
*/
38-
StandardOperationResponse(HttpStatus status, HttpHeaders headers, byte[] content) {
38+
StandardOperationResponse(int status, HttpHeaders headers, byte[] content) {
3939
super(content, headers);
4040
this.status = status;
4141
}
4242

4343
@Override
4444
public HttpStatus getStatus() {
45+
return HttpStatus.resolve(this.status);
46+
}
47+
48+
@Override
49+
public int getStatusCode() {
4550
return this.status;
4651
}
4752

spring-restdocs-core/src/main/java/org/springframework/restdocs/operation/preprocess/UriModifyingOperationPreprocessor.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,7 @@ public OperationRequest preprocess(OperationRequest request) {
141141

142142
@Override
143143
public OperationResponse preprocess(OperationResponse response) {
144-
return this.contentModifyingDelegate.preprocess(new OperationResponseFactory().create(response.getStatus(),
144+
return this.contentModifyingDelegate.preprocess(new OperationResponseFactory().create(response.getStatusCode(),
145145
modify(response.getHeaders()), response.getContent()));
146146
}
147147

spring-restdocs-core/src/test/java/org/springframework/restdocs/RestDocumentationGeneratorTests.java

+2-2
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ public class RestDocumentationGeneratorTests {
6969
private final OperationRequest operationRequest = new OperationRequestFactory()
7070
.create(URI.create("http://localhost:8080"), null, null, new HttpHeaders(), null, null);
7171

72-
private final OperationResponse operationResponse = new OperationResponseFactory().create(null, null, null);
72+
private final OperationResponse operationResponse = new OperationResponseFactory().create(0, null, null);
7373

7474
private final Snippet snippet = mock(Snippet.class);
7575

@@ -197,7 +197,7 @@ private static OperationRequest createRequest() {
197197
}
198198

199199
private static OperationResponse createResponse() {
200-
return new OperationResponseFactory().create(null, null, null);
200+
return new OperationResponseFactory().create(0, null, null);
201201
}
202202

203203
}

spring-restdocs-core/src/test/java/org/springframework/restdocs/config/RestDocumentationConfigurerTests.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -217,7 +217,7 @@ public void customDefaultOperationResponsePreprocessor() {
217217
.get(RestDocumentationGenerator.ATTRIBUTE_NAME_DEFAULT_OPERATION_RESPONSE_PREPROCESSOR);
218218
HttpHeaders headers = new HttpHeaders();
219219
headers.add("Foo", "value");
220-
OperationResponse response = new OperationResponseFactory().create(HttpStatus.OK, headers, null);
220+
OperationResponse response = new OperationResponseFactory().create(HttpStatus.OK.value(), headers, null);
221221
assertThat(preprocessor.preprocess(response).getHeaders()).doesNotContainKey("Foo");
222222
}
223223

spring-restdocs-core/src/test/java/org/springframework/restdocs/hypermedia/ContentTypeLinkExtractorTests.java

+3-3
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ public class ContentTypeLinkExtractorTests {
4949
public void extractionFailsWithNullContentType() throws IOException {
5050
this.thrown.expect(IllegalStateException.class);
5151
new ContentTypeLinkExtractor()
52-
.extractLinks(this.responseFactory.create(HttpStatus.OK, new HttpHeaders(), null));
52+
.extractLinks(this.responseFactory.create(HttpStatus.OK.value(), new HttpHeaders(), null));
5353
}
5454

5555
@Test
@@ -59,7 +59,7 @@ public void extractorCalledWithMatchingContextType() throws IOException {
5959
extractors.put(MediaType.APPLICATION_JSON, extractor);
6060
HttpHeaders httpHeaders = new HttpHeaders();
6161
httpHeaders.setContentType(MediaType.APPLICATION_JSON);
62-
OperationResponse response = this.responseFactory.create(HttpStatus.OK, httpHeaders, null);
62+
OperationResponse response = this.responseFactory.create(HttpStatus.OK.value(), httpHeaders, null);
6363
new ContentTypeLinkExtractor(extractors).extractLinks(response);
6464
verify(extractor).extractLinks(response);
6565
}
@@ -71,7 +71,7 @@ public void extractorCalledWithCompatibleContextType() throws IOException {
7171
extractors.put(MediaType.APPLICATION_JSON, extractor);
7272
HttpHeaders httpHeaders = new HttpHeaders();
7373
httpHeaders.setContentType(MediaType.parseMediaType("application/json;foo=bar"));
74-
OperationResponse response = this.responseFactory.create(HttpStatus.OK, httpHeaders, null);
74+
OperationResponse response = this.responseFactory.create(HttpStatus.OK.value(), httpHeaders, null);
7575
new ContentTypeLinkExtractor(extractors).extractLinks(response);
7676
verify(extractor).extractLinks(response);
7777
}

spring-restdocs-core/src/test/java/org/springframework/restdocs/hypermedia/LinkExtractorsPayloadTests.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@ private void assertLinks(List<Link> expectedLinks, Map<String, List<Link>> actua
106106
}
107107

108108
private OperationResponse createResponse(String contentName) throws IOException {
109-
return this.responseFactory.create(HttpStatus.OK, null,
109+
return this.responseFactory.create(HttpStatus.OK.value(), null,
110110
FileCopyUtils.copyToByteArray(getPayloadFile(contentName)));
111111
}
112112

spring-restdocs-core/src/test/java/org/springframework/restdocs/operation/preprocess/ContentModifyingOperationPreprocessorTests.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ public void modifyRequestContent() {
6767

6868
@Test
6969
public void modifyResponseContent() {
70-
OperationResponse response = this.responseFactory.create(HttpStatus.OK, new HttpHeaders(),
70+
OperationResponse response = this.responseFactory.create(HttpStatus.OK.value(), new HttpHeaders(),
7171
"content".getBytes());
7272
OperationResponse preprocessed = this.preprocessor.preprocess(response);
7373
assertThat(preprocessed.getContent()).isEqualTo("modified".getBytes());

spring-restdocs-core/src/test/java/org/springframework/restdocs/operation/preprocess/HeaderRemovingOperationPreprocessorTests.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ public void removeAllHeaders() {
8787
}
8888

8989
private OperationResponse createResponse(String... extraHeaders) {
90-
return this.responseFactory.create(HttpStatus.OK, getHttpHeaders(extraHeaders), new byte[0]);
90+
return this.responseFactory.create(HttpStatus.OK.value(), getHttpHeaders(extraHeaders), new byte[0]);
9191
}
9292

9393
private HttpHeaders getHttpHeaders(String... extraHeaders) {

spring-restdocs-core/src/test/java/org/springframework/restdocs/operation/preprocess/UriModifyingOperationPreprocessorTests.java

+2-2
Original file line numberDiff line numberDiff line change
@@ -321,13 +321,13 @@ private OperationRequest createRequestWithPartWithContent(String content) {
321321
}
322322

323323
private OperationResponse createResponseWithContent(String content) {
324-
return this.responseFactory.create(HttpStatus.OK, new HttpHeaders(), content.getBytes());
324+
return this.responseFactory.create(HttpStatus.OK.value(), new HttpHeaders(), content.getBytes());
325325
}
326326

327327
private OperationResponse createResponseWithHeader(String name, String value) {
328328
HttpHeaders headers = new HttpHeaders();
329329
headers.add(name, value);
330-
return this.responseFactory.create(HttpStatus.OK, headers, new byte[0]);
330+
return this.responseFactory.create(HttpStatus.OK.value(), headers, new byte[0]);
331331
}
332332

333333
}

spring-restdocs-core/src/test/java/org/springframework/restdocs/test/OperationBuilder.java

+2-2
Original file line numberDiff line numberDiff line change
@@ -261,7 +261,7 @@ public OperationRequestPartBuilder header(String name, String value) {
261261
*/
262262
public final class OperationResponseBuilder {
263263

264-
private HttpStatus status = HttpStatus.OK;
264+
private int status = HttpStatus.OK.value();
265265

266266
private HttpHeaders headers = new HttpHeaders();
267267

@@ -272,7 +272,7 @@ private OperationResponse buildResponse() {
272272
}
273273

274274
public OperationResponseBuilder status(int status) {
275-
this.status = HttpStatus.valueOf(status);
275+
this.status = status;
276276
return this;
277277
}
278278

spring-restdocs-mockmvc/src/main/java/org/springframework/restdocs/mockmvc/MockMvcResponseConverter.java

+2-3
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@
1919
import javax.servlet.http.Cookie;
2020

2121
import org.springframework.http.HttpHeaders;
22-
import org.springframework.http.HttpStatus;
2322
import org.springframework.mock.web.MockHttpServletResponse;
2423
import org.springframework.restdocs.operation.OperationResponse;
2524
import org.springframework.restdocs.operation.OperationResponseFactory;
@@ -36,8 +35,8 @@ class MockMvcResponseConverter implements ResponseConverter<MockHttpServletRespo
3635

3736
@Override
3837
public OperationResponse convert(MockHttpServletResponse mockResponse) {
39-
return new OperationResponseFactory().create(HttpStatus.valueOf(mockResponse.getStatus()),
40-
extractHeaders(mockResponse), mockResponse.getContentAsByteArray());
38+
return new OperationResponseFactory().create(mockResponse.getStatus(), extractHeaders(mockResponse),
39+
mockResponse.getContentAsByteArray());
4140
}
4241

4342
private HttpHeaders extractHeaders(MockHttpServletResponse response) {

spring-restdocs-mockmvc/src/test/java/org/springframework/restdocs/mockmvc/MockMvcResponseConverterTests.java

+10-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2014-2018 the original author or authors.
2+
* Copyright 2014-2019 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -61,4 +61,13 @@ public void responseWithCookie() {
6161
Collections.singletonList("name=value; Domain=localhost; HttpOnly"));
6262
}
6363

64+
@Test
65+
public void responseWithCustomStatus() {
66+
MockHttpServletResponse response = new MockHttpServletResponse();
67+
response.setStatus(600);
68+
OperationResponse operationResponse = this.factory.convert(response);
69+
assertThat(operationResponse.getStatus()).isNull();
70+
assertThat(operationResponse.getStatusCode()).isEqualTo(600);
71+
}
72+
6473
}

spring-restdocs-restassured/src/main/java/org/springframework/restdocs/restassured3/RestAssuredResponseConverter.java

+2-3
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@
2020
import io.restassured.response.Response;
2121

2222
import org.springframework.http.HttpHeaders;
23-
import org.springframework.http.HttpStatus;
2423
import org.springframework.restdocs.operation.OperationResponse;
2524
import org.springframework.restdocs.operation.OperationResponseFactory;
2625
import org.springframework.restdocs.operation.ResponseConverter;
@@ -35,8 +34,8 @@ class RestAssuredResponseConverter implements ResponseConverter<Response> {
3534

3635
@Override
3736
public OperationResponse convert(Response response) {
38-
return new OperationResponseFactory().create(HttpStatus.valueOf(response.getStatusCode()),
39-
extractHeaders(response), extractContent(response));
37+
return new OperationResponseFactory().create(response.getStatusCode(), extractHeaders(response),
38+
extractContent(response));
4039
}
4140

4241
private HttpHeaders extractHeaders(Response response) {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
/*
2+
* Copyright 2014-2019 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.springframework.restdocs.restassured3;
18+
19+
import io.restassured.http.Headers;
20+
import io.restassured.response.Response;
21+
import io.restassured.response.ResponseBody;
22+
import org.junit.Test;
23+
24+
import org.springframework.restdocs.operation.OperationResponse;
25+
26+
import static org.assertj.core.api.Assertions.assertThat;
27+
import static org.mockito.BDDMockito.given;
28+
import static org.mockito.Mockito.mock;
29+
30+
/**
31+
* Tests for {@link RestAssuredResponseConverter}.
32+
*
33+
* @author Andy Wilkinson
34+
*/
35+
public class RestAssuredResponseConverterTests {
36+
37+
private final RestAssuredResponseConverter converter = new RestAssuredResponseConverter();
38+
39+
@Test
40+
public void responseWithCustomStatus() {
41+
Response response = mock(Response.class);
42+
given(response.getStatusCode()).willReturn(600);
43+
given(response.getHeaders()).willReturn(new Headers());
44+
ResponseBody<?> body = mock(ResponseBody.class);
45+
given(response.getBody()).willReturn(body);
46+
given(body.asByteArray()).willReturn(new byte[0]);
47+
OperationResponse operationResponse = this.converter.convert(response);
48+
assertThat(operationResponse.getStatus()).isNull();
49+
assertThat(operationResponse.getStatusCode()).isEqualTo(600);
50+
}
51+
52+
}

spring-restdocs-webtestclient/src/main/java/org/springframework/restdocs/webtestclient/WebTestClientResponseConverter.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ class WebTestClientResponseConverter implements ResponseConverter<ExchangeResult
3636

3737
@Override
3838
public OperationResponse convert(ExchangeResult result) {
39-
return new OperationResponseFactory().create(result.getStatus(), extractHeaders(result),
39+
return new OperationResponseFactory().create(result.getStatus().value(), extractHeaders(result),
4040
result.getResponseBodyContent());
4141
}
4242

0 commit comments

Comments
 (0)