Skip to content

Commit 895d43a

Browse files
committed
Print cookies in human-readable form in Spring MVC Test
Prior to this commit, when rendering cookies via `andDo(print())` in Spring MVC Test, the output for the `MockHttpServletResponse` would look something like the following: Cookies = [javax.servlet.http.Cookie@25084a1e] The reason is that the Cookie class in javax.servlet-api-3.0.1.jar does not implement toString(). Consequently, nothing about the cookie's name, value, etc., is displayed, thereby making the debug output for cookies next to useless. This commit improves on this by implementing custom toString() logic for cookies in debug output in Spring MVC Test. For example, the output now looks like this (without the newlines): Cookies = [[Cookie@47faa49c name = 'enigma', value = '42', \\ comment = [null], domain = [null], maxAge = -1, \\ path = [null], secure = false, version = 0, \\ httpOnly = false]] In addition, this commit fixes a minor bug for FlashMap debug output if the FlashMap is empty. Issue: SPR-13168
1 parent a2d3c27 commit 895d43a

File tree

4 files changed

+97
-46
lines changed

4 files changed

+97
-46
lines changed

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

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,10 @@
2424
* Static, factory methods for {@link ResultHandler}-based result actions.
2525
*
2626
* <p><strong>Eclipse users:</strong> consider adding this class as a Java editor
27-
* favorite. To navigate, open the Preferences and type "favorites".
27+
* favorite. To navigate to this setting, open the Preferences and type "favorites".
2828
*
2929
* @author Rossen Stoyanchev
30+
* @author Sam Brannen
3031
* @since 3.2
3132
*/
3233
public abstract class MockMvcResultHandlers {
@@ -49,14 +50,14 @@ public ConsolePrintingResultHandler() {
4950
@Override
5051
public void printHeading(String heading) {
5152
System.out.println();
52-
System.out.println(String.format("%20s:", heading));
53+
System.out.println(String.format("%s:", heading));
5354
}
5455
@Override
5556
public void printValue(String label, Object value) {
5657
if (value != null && value.getClass().isArray()) {
5758
value = CollectionUtils.arrayToList(value);
5859
}
59-
System.out.println(String.format("%20s = %s", label, value));
60+
System.out.println(String.format("%17s = %s", label, value));
6061
}
6162
});
6263
}

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

Lines changed: 34 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,15 +18,19 @@
1818

1919
import java.util.Enumeration;
2020
import java.util.Map;
21+
22+
import javax.servlet.http.Cookie;
2123
import javax.servlet.http.HttpServletRequest;
2224

25+
import org.springframework.core.style.ToStringCreator;
2326
import org.springframework.http.HttpHeaders;
2427
import org.springframework.mock.web.MockHttpServletRequest;
2528
import org.springframework.mock.web.MockHttpServletResponse;
2629
import org.springframework.test.web.servlet.MvcResult;
2730
import org.springframework.test.web.servlet.ResultHandler;
2831
import org.springframework.util.LinkedMultiValueMap;
2932
import org.springframework.util.MultiValueMap;
33+
import org.springframework.util.ObjectUtils;
3034
import org.springframework.validation.BindingResult;
3135
import org.springframework.validation.Errors;
3236
import org.springframework.web.method.HandlerMethod;
@@ -37,10 +41,12 @@
3741

3842
/**
3943
* Result handler that prints {@link MvcResult} details to the "standard" output
40-
* stream. An instance of this class is typically accessed via
44+
* stream.
45+
* <p>An instance of this class is typically accessed via
4146
* {@link MockMvcResultHandlers#print()}.
4247
*
4348
* @author Rossen Stoyanchev
49+
* @author Sam Brannen
4450
* @since 3.2
4551
*/
4652
public class PrintingResultHandler implements ResultHandler {
@@ -57,7 +63,7 @@ protected PrintingResultHandler(ResultValuePrinter printer) {
5763
}
5864

5965
/**
60-
* @return the result value printer.
66+
* @return the result value printer
6167
*/
6268
protected ResultValuePrinter getPrinter() {
6369
return this.printer;
@@ -198,7 +204,7 @@ protected void printModelAndView(ModelAndView mav) throws Exception {
198204
* Print "output" flash attributes.
199205
*/
200206
protected void printFlashMap(FlashMap flashMap) throws Exception {
201-
if (flashMap == null) {
207+
if (ObjectUtils.isEmpty(flashMap)) {
202208
this.printer.printValue("Attributes", null);
203209
}
204210
else {
@@ -220,7 +226,31 @@ protected void printResponse(MockHttpServletResponse response) throws Exception
220226
this.printer.printValue("Body", response.getContentAsString());
221227
this.printer.printValue("Forwarded URL", response.getForwardedUrl());
222228
this.printer.printValue("Redirected URL", response.getRedirectedUrl());
223-
this.printer.printValue("Cookies", response.getCookies());
229+
printCookies(response.getCookies());
230+
}
231+
232+
/**
233+
* Print the supplied cookies in a human-readable form, assuming the
234+
* {@link Cookie} implementation does not provide its own {@code toString()}.
235+
* @since 4.2
236+
*/
237+
private void printCookies(Cookie[] cookies) {
238+
String[] cookieStrings = new String[cookies.length];
239+
for (int i = 0; i < cookies.length; i++) {
240+
Cookie cookie = cookies[i];
241+
cookieStrings[i] = new ToStringCreator(cookie)
242+
.append("name", cookie.getName())
243+
.append("value", cookie.getValue())
244+
.append("comment", cookie.getComment())
245+
.append("domain", cookie.getDomain())
246+
.append("maxAge", cookie.getMaxAge())
247+
.append("path", cookie.getPath())
248+
.append("secure", cookie.getSecure())
249+
.append("version", cookie.getVersion())
250+
.append("httpOnly", cookie.isHttpOnly())
251+
.toString();
252+
}
253+
this.printer.printValue("Cookies", cookieStrings);
224254
}
225255

226256
protected final HttpHeaders getResponseHeaders(MockHttpServletResponse response) {

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

Lines changed: 53 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2014 the original author or authors.
2+
* Copyright 2002-2015 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.
@@ -19,9 +19,9 @@
1919
import java.net.URI;
2020
import java.util.HashMap;
2121
import java.util.Map;
22+
2223
import javax.servlet.http.Cookie;
2324

24-
import org.junit.Before;
2525
import org.junit.Test;
2626

2727
import org.springframework.http.HttpHeaders;
@@ -45,33 +45,27 @@
4545
* Tests for {@link PrintingResultHandler}.
4646
*
4747
* @author Rossen Stoyanchev
48+
* @author Sam Brannen
4849
*/
4950
public class PrintingResultHandlerTests {
5051

51-
private TestPrintingResultHandler handler;
52-
53-
private MockHttpServletRequest request;
52+
private final TestPrintingResultHandler handler = new TestPrintingResultHandler();
5453

55-
private MockHttpServletResponse response;
54+
private final MockHttpServletRequest request = new MockHttpServletRequest("GET", "/") {
55+
@Override
56+
public boolean isAsyncStarted() {
57+
return false;
58+
}
59+
};
5660

57-
private StubMvcResult mvcResult;
61+
private final MockHttpServletResponse response = new MockHttpServletResponse();
5862

63+
private final StubMvcResult mvcResult = new StubMvcResult(this.request, null, null,
64+
null, null, null, this.response);
5965

60-
@Before
61-
public void setup() {
62-
this.handler = new TestPrintingResultHandler();
63-
this.request = new MockHttpServletRequest("GET", "/") {
64-
@Override
65-
public boolean isAsyncStarted() {
66-
return false;
67-
}
68-
};
69-
this.response = new MockHttpServletResponse();
70-
this.mvcResult = new StubMvcResult(this.request, null, null, null, null, null, this.response);
71-
}
7266

7367
@Test
74-
public void testPrintRequest() throws Exception {
68+
public void printRequest() throws Exception {
7569
this.request.addParameter("param", "paramValue");
7670
this.request.addHeader("header", "headerValue");
7771

@@ -91,14 +85,23 @@ public void testPrintRequest() throws Exception {
9185

9286
@Test
9387
@SuppressWarnings("deprecation")
94-
public void testPrintResponse() throws Exception {
88+
public void printResponse() throws Exception {
89+
Cookie enigmaCookie = new Cookie("enigma", "42");
90+
enigmaCookie.setComment("This is a comment");
91+
enigmaCookie.setHttpOnly(true);
92+
enigmaCookie.setMaxAge(1234);
93+
enigmaCookie.setDomain(".example.com");
94+
enigmaCookie.setPath("/crumbs");
95+
enigmaCookie.setSecure(true);
96+
9597
this.response.setStatus(400, "error");
9698
this.response.addHeader("header", "headerValue");
9799
this.response.setContentType("text/plain");
98100
this.response.getWriter().print("content");
99101
this.response.setForwardedUrl("redirectFoo");
100102
this.response.sendRedirect("/redirectFoo");
101103
this.response.addCookie(new Cookie("cookie", "cookieValue"));
104+
this.response.addCookie(enigmaCookie);
102105

103106
this.handler.handle(this.mvcResult);
104107

@@ -107,33 +110,46 @@ public void testPrintResponse() throws Exception {
107110
headers.setContentType(MediaType.TEXT_PLAIN);
108111
headers.setLocation(new URI("/redirectFoo"));
109112

110-
assertValue("MockHttpServletResponse", "Status", this.response.getStatus());
111-
assertValue("MockHttpServletResponse", "Error message", response.getErrorMessage());
112-
assertValue("MockHttpServletResponse", "Headers", headers);
113-
assertValue("MockHttpServletResponse", "Content type", this.response.getContentType());
114-
assertValue("MockHttpServletResponse", "Body", this.response.getContentAsString());
115-
assertValue("MockHttpServletResponse", "Forwarded URL", this.response.getForwardedUrl());
116-
assertValue("MockHttpServletResponse", "Redirected URL", this.response.getRedirectedUrl());
113+
String heading = "MockHttpServletResponse";
114+
assertValue(heading, "Status", this.response.getStatus());
115+
assertValue(heading, "Error message", response.getErrorMessage());
116+
assertValue(heading, "Headers", headers);
117+
assertValue(heading, "Content type", this.response.getContentType());
118+
assertValue(heading, "Body", this.response.getContentAsString());
119+
assertValue(heading, "Forwarded URL", this.response.getForwardedUrl());
120+
assertValue(heading, "Redirected URL", this.response.getRedirectedUrl());
121+
122+
Map<String, Map<String, Object>> printedValues = this.handler.getPrinter().printedValues;
123+
String[] cookies = (String[]) printedValues.get(heading).get("Cookies");
124+
assertEquals(2, cookies.length);
125+
String cookie1 = cookies[0];
126+
String cookie2 = cookies[1];
127+
assertTrue(cookie1.startsWith("[" + Cookie.class.getSimpleName()));
128+
assertTrue(cookie1.contains("name = 'cookie', value = 'cookieValue'"));
129+
assertTrue(cookie1.endsWith("]"));
130+
assertTrue(cookie2.startsWith("[" + Cookie.class.getSimpleName()));
131+
assertTrue(cookie2.contains("name = 'enigma', value = '42', comment = 'This is a comment', domain = '.example.com', maxAge = 1234, path = '/crumbs', secure = true, version = 0, httpOnly = true"));
132+
assertTrue(cookie2.endsWith("]"));
117133
}
118134

119135
@Test
120-
public void testPrintHandlerNull() throws Exception {
136+
public void printHandlerNull() throws Exception {
121137
StubMvcResult mvcResult = new StubMvcResult(this.request, null, null, null, null, null, this.response);
122138
this.handler.handle(mvcResult);
123139

124140
assertValue("Handler", "Type", null);
125141
}
126142

127143
@Test
128-
public void testPrintHandler() throws Exception {
144+
public void printHandler() throws Exception {
129145
this.mvcResult.setHandler(new Object());
130146
this.handler.handle(this.mvcResult);
131147

132148
assertValue("Handler", "Type", Object.class.getName());
133149
}
134150

135151
@Test
136-
public void testPrintHandlerMethod() throws Exception {
152+
public void printHandlerMethod() throws Exception {
137153
HandlerMethod handlerMethod = new HandlerMethod(this, "handle");
138154
this.mvcResult.setHandler(handlerMethod);
139155
this.handler.handle(mvcResult);
@@ -143,22 +159,22 @@ public void testPrintHandlerMethod() throws Exception {
143159
}
144160

145161
@Test
146-
public void testResolvedExceptionNull() throws Exception {
162+
public void resolvedExceptionNull() throws Exception {
147163
this.handler.handle(this.mvcResult);
148164

149165
assertValue("Resolved Exception", "Type", null);
150166
}
151167

152168
@Test
153-
public void testResolvedException() throws Exception {
169+
public void resolvedException() throws Exception {
154170
this.mvcResult.setResolvedException(new Exception());
155171
this.handler.handle(this.mvcResult);
156172

157173
assertValue("Resolved Exception", "Type", Exception.class.getName());
158174
}
159175

160176
@Test
161-
public void testModelAndViewNull() throws Exception {
177+
public void modelAndViewNull() throws Exception {
162178
this.handler.handle(this.mvcResult);
163179

164180
assertValue("ModelAndView", "View name", null);
@@ -167,7 +183,7 @@ public void testModelAndViewNull() throws Exception {
167183
}
168184

169185
@Test
170-
public void testModelAndView() throws Exception {
186+
public void modelAndView() throws Exception {
171187
BindException bindException = new BindException(new Object(), "target");
172188
bindException.reject("errorCode");
173189

@@ -186,14 +202,14 @@ public void testModelAndView() throws Exception {
186202
}
187203

188204
@Test
189-
public void testFlashMapNull() throws Exception {
205+
public void flashMapNull() throws Exception {
190206
this.handler.handle(mvcResult);
191207

192208
assertValue("FlashMap", "Type", null);
193209
}
194210

195211
@Test
196-
public void testFlashMap() throws Exception {
212+
public void flashMap() throws Exception {
197213
FlashMap flashMap = new FlashMap();
198214
flashMap.put("attrName", "attrValue");
199215
this.request.setAttribute(DispatcherServlet.class.getName() + ".OUTPUT_FLASH_MAP", flashMap);

spring-test/src/test/java/org/springframework/test/web/servlet/samples/standalone/resulthandlers/PrintingResultHandlerTests.java

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2014 the original author or authors.
2+
* Copyright 2002-2015 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.
@@ -16,6 +16,9 @@
1616

1717
package org.springframework.test.web.servlet.samples.standalone.resulthandlers;
1818

19+
import javax.servlet.http.Cookie;
20+
import javax.servlet.http.HttpServletResponse;
21+
1922
import org.junit.Ignore;
2023
import org.junit.Test;
2124

@@ -47,7 +50,8 @@ private static class SimpleController {
4750

4851
@RequestMapping("/")
4952
@ResponseBody
50-
public String hello() {
53+
public String hello(HttpServletResponse response) {
54+
response.addCookie(new Cookie("enigma", "42"));
5155
return "Hello world";
5256
}
5357
}

0 commit comments

Comments
 (0)