Skip to content

Commit e65a1a4

Browse files
committed
Print only printable request/response body in MVC Test
Prior to this commit, PrintingResultHandler always printed the request or response body regardless of its content type. For binary content, however, the output was unreadable and therefore useless. This commit addresses this issue by only printing the request or response body if it is "printable" (i.e., if its content type is known to be text-based such as plain text, HTML, XHTML, XML, JSON, etc.). If the content type is unknown (e.g., unspecified for the HTTP request in the test), it is assumed that the body is printable. Issue: SPR-14776
1 parent 7ae7294 commit e65a1a4

File tree

2 files changed

+85
-3
lines changed

2 files changed

+85
-3
lines changed

spring-test/src/main/java/org/springframework/test/web/servlet/result/PrintingResultHandler.java

Lines changed: 37 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,9 @@
1616

1717
package org.springframework.test.web.servlet.result;
1818

19+
import java.util.Arrays;
1920
import java.util.Enumeration;
21+
import java.util.List;
2022
import java.util.Map;
2123

2224
import javax.servlet.http.Cookie;
@@ -29,6 +31,8 @@
2931
import org.springframework.test.web.servlet.MvcResult;
3032
import org.springframework.test.web.servlet.ResultHandler;
3133
import org.springframework.util.LinkedMultiValueMap;
34+
import org.springframework.util.MimeType;
35+
import org.springframework.util.MimeTypeUtils;
3236
import org.springframework.util.MultiValueMap;
3337
import org.springframework.util.ObjectUtils;
3438
import org.springframework.validation.BindingResult;
@@ -54,6 +58,14 @@
5458
*/
5559
public class PrintingResultHandler implements ResultHandler {
5660

61+
private static final String NOT_PRINTABLE = "<content type is not printable text>";
62+
63+
private static final List<MimeType> printableMimeTypes = Arrays.asList(
64+
MimeTypeUtils.APPLICATION_JSON, MimeTypeUtils.APPLICATION_XML,
65+
new MimeType("text", "*"), new MimeType("application", "*+json"),
66+
new MimeType("application", "*+xml"));
67+
68+
5769
private final ResultValuePrinter printer;
5870

5971

@@ -103,11 +115,14 @@ public final void handle(MvcResult result) throws Exception {
103115
* Print the request.
104116
*/
105117
protected void printRequest(MockHttpServletRequest request) throws Exception {
118+
String body = (isPrintableContentType(request.getContentType()) ?
119+
request.getContentAsString() : NOT_PRINTABLE);
120+
106121
this.printer.printValue("HTTP Method", request.getMethod());
107122
this.printer.printValue("Request URI", request.getRequestURI());
108123
this.printer.printValue("Parameters", getParamsMultiValueMap(request));
109124
this.printer.printValue("Headers", getRequestHeaders(request));
110-
this.printer.printValue("Body", request.getContentAsString());
125+
this.printer.printValue("Body", body);
111126
}
112127

113128
protected final HttpHeaders getRequestHeaders(MockHttpServletRequest request) {
@@ -223,11 +238,14 @@ protected void printFlashMap(FlashMap flashMap) throws Exception {
223238
* Print the response.
224239
*/
225240
protected void printResponse(MockHttpServletResponse response) throws Exception {
241+
String body = (isPrintableContentType(response.getContentType()) ?
242+
response.getContentAsString() : NOT_PRINTABLE);
243+
226244
this.printer.printValue("Status", response.getStatus());
227245
this.printer.printValue("Error message", response.getErrorMessage());
228246
this.printer.printValue("Headers", getResponseHeaders(response));
229247
this.printer.printValue("Content type", response.getContentType());
230-
this.printer.printValue("Body", response.getContentAsString());
248+
this.printer.printValue("Body", body);
231249
this.printer.printValue("Forwarded URL", response.getForwardedUrl());
232250
this.printer.printValue("Redirected URL", response.getRedirectedUrl());
233251
printCookies(response.getCookies());
@@ -266,6 +284,23 @@ protected final HttpHeaders getResponseHeaders(MockHttpServletResponse response)
266284
}
267285

268286

287+
/**
288+
* Determine if the supplied content type is <em>printable</em> (i.e., text-based).
289+
* <p>If the supplied content type is {@code null} (i.e., unknown), this method
290+
* assumes that the content is printable by default and returns {@code true}.
291+
* @param contentType the content type to check; {@code null} if unknown
292+
* @return {@code true} if the content type is known to be or assumed to be printable
293+
* @since 5.0
294+
*/
295+
private static boolean isPrintableContentType(String contentType) {
296+
if (contentType == null) {
297+
return true;
298+
}
299+
MimeType mimeType = MimeType.valueOf(contentType);
300+
return printableMimeTypes.stream().anyMatch(printable -> printable.includes(mimeType));
301+
}
302+
303+
269304
/**
270305
* A contract for how to actually write result information.
271306
*/

spring-test/src/test/java/org/springframework/test/web/servlet/result/PrintingResultHandlerTests.java

Lines changed: 48 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,9 @@
1717
package org.springframework.test.web.servlet.result;
1818

1919
import java.net.URI;
20+
import java.util.Arrays;
2021
import java.util.HashMap;
22+
import java.util.List;
2123
import java.util.Map;
2224

2325
import javax.servlet.http.Cookie;
@@ -31,6 +33,7 @@
3133
import org.springframework.test.web.servlet.StubMvcResult;
3234
import org.springframework.util.Assert;
3335
import org.springframework.util.LinkedMultiValueMap;
36+
import org.springframework.util.MimeTypeUtils;
3437
import org.springframework.util.MultiValueMap;
3538
import org.springframework.validation.BindException;
3639
import org.springframework.validation.BindingResult;
@@ -50,6 +53,11 @@
5053
*/
5154
public class PrintingResultHandlerTests {
5255

56+
private static final List<String> textContentTypes = Arrays.asList(MimeTypeUtils.APPLICATION_JSON_VALUE,
57+
MimeTypeUtils.APPLICATION_XML_VALUE, MimeTypeUtils.APPLICATION_XHTML_XML_VALUE,
58+
MimeTypeUtils.TEXT_HTML_VALUE, MimeTypeUtils.TEXT_PLAIN_VALUE);
59+
60+
5361
private final TestPrintingResultHandler handler = new TestPrintingResultHandler();
5462

5563
private final MockHttpServletRequest request = new MockHttpServletRequest("GET", "/") {
@@ -82,7 +90,6 @@ public void printRequest() throws Exception {
8290
MultiValueMap<String, String> params = new LinkedMultiValueMap<>();
8391
params.add("param", "paramValue");
8492

85-
8693
assertValue("MockHttpServletRequest", "HTTP Method", this.request.getMethod());
8794
assertValue("MockHttpServletRequest", "Request URI", this.request.getRequestURI());
8895
assertValue("MockHttpServletRequest", "Parameters", params);
@@ -139,6 +146,46 @@ public void printResponse() throws Exception {
139146
assertTrue(cookie2.endsWith("]"));
140147
}
141148

149+
@Test
150+
public void printRequestWithTextContentTypes() throws Exception {
151+
this.request.setContent("text".getBytes());
152+
153+
for (String contentType: textContentTypes) {
154+
this.request.setContentType(contentType);
155+
this.handler.handle(this.mvcResult);
156+
assertValue("MockHttpServletRequest", "Body", "text");
157+
}
158+
}
159+
160+
@Test
161+
public void printResponseWithTextContentTypes() throws Exception {
162+
this.response.getWriter().print("text");
163+
164+
for (String contentType: textContentTypes) {
165+
this.response.setContentType(contentType);
166+
this.handler.handle(this.mvcResult);
167+
assertValue("MockHttpServletResponse", "Body", "text");
168+
}
169+
}
170+
171+
@Test
172+
public void printRequestWithBinaryContentType() throws Exception {
173+
this.request.setContentType(MimeTypeUtils.IMAGE_JPEG_VALUE);
174+
175+
this.handler.handle(this.mvcResult);
176+
177+
assertValue("MockHttpServletRequest", "Body", "<content type is not printable text>");
178+
}
179+
180+
@Test
181+
public void printResponseWithBinaryContentType() throws Exception {
182+
this.response.setContentType(MimeTypeUtils.IMAGE_JPEG_VALUE);
183+
184+
this.handler.handle(this.mvcResult);
185+
186+
assertValue("MockHttpServletResponse", "Body", "<content type is not printable text>");
187+
}
188+
142189
@Test
143190
public void printHandlerNull() throws Exception {
144191
StubMvcResult mvcResult = new StubMvcResult(this.request, null, null, null, null, null, this.response);

0 commit comments

Comments
 (0)