diff --git a/spring-test-mvc/src/main/java/org/springframework/test/web/servlet/DefaultMvcResult.java b/spring-test-mvc/src/main/java/org/springframework/test/web/servlet/DefaultMvcResult.java index fe1af58a09b..275287c7336 100644 --- a/spring-test-mvc/src/main/java/org/springframework/test/web/servlet/DefaultMvcResult.java +++ b/spring-test-mvc/src/main/java/org/springframework/test/web/servlet/DefaultMvcResult.java @@ -110,9 +110,13 @@ class DefaultMvcResult implements MvcResult { } public Object getAsyncResult() { + return getAsyncResult(-1); + } + + public Object getAsyncResult(long timeout) { HttpServletRequest request = this.mockRequest; - if (request.isAsyncStarted()) { - if (!awaitAsyncResult(request)) { + if ((timeout != 0) && request.isAsyncStarted()) { + if (!awaitAsyncResult(request, timeout)) { throw new IllegalStateException( "Gave up waiting on async result from handler [" + this.handler + "] to complete"); } @@ -120,8 +124,10 @@ class DefaultMvcResult implements MvcResult { return this.asyncResult; } - private boolean awaitAsyncResult(HttpServletRequest request) { - long timeout = request.getAsyncContext().getTimeout(); + private boolean awaitAsyncResult(HttpServletRequest request, long timeout) { + if (timeout != -1) { + timeout = request.getAsyncContext().getTimeout(); + } if (this.asyncResultLatch != null) { try { return this.asyncResultLatch.await(timeout, TimeUnit.MILLISECONDS); diff --git a/spring-test-mvc/src/main/java/org/springframework/test/web/servlet/MvcResult.java b/spring-test-mvc/src/main/java/org/springframework/test/web/servlet/MvcResult.java index c24ba48365c..f886e7bc1f3 100644 --- a/spring-test-mvc/src/main/java/org/springframework/test/web/servlet/MvcResult.java +++ b/spring-test-mvc/src/main/java/org/springframework/test/web/servlet/MvcResult.java @@ -85,4 +85,15 @@ public interface MvcResult { */ Object getAsyncResult(); + /** + * Get the result of asynchronous execution or {@code null} if concurrent + * handling did not start. This method will wait for up to the given timeout + * for the completion of concurrent handling. + * + * @param timeout how long to wait for the async result to be set in + * milliseconds; if -1, the wait will be as long as the async timeout set + * on the Servlet request + */ + Object getAsyncResult(long timeout); + } diff --git a/spring-test-mvc/src/main/java/org/springframework/test/web/servlet/result/PrintingResultHandler.java b/spring-test-mvc/src/main/java/org/springframework/test/web/servlet/result/PrintingResultHandler.java index 73a67ce8bb7..703ecd57783 100644 --- a/spring-test-mvc/src/main/java/org/springframework/test/web/servlet/result/PrintingResultHandler.java +++ b/spring-test-mvc/src/main/java/org/springframework/test/web/servlet/result/PrintingResultHandler.java @@ -17,12 +17,18 @@ package org.springframework.test.web.servlet.result; import java.util.Enumeration; +import java.util.Map; + +import javax.servlet.ServletRequest; import org.springframework.http.HttpHeaders; import org.springframework.mock.web.MockHttpServletRequest; import org.springframework.mock.web.MockHttpServletResponse; import org.springframework.test.web.servlet.MvcResult; import org.springframework.test.web.servlet.ResultHandler; +import org.springframework.util.ClassUtils; +import org.springframework.util.LinkedMultiValueMap; +import org.springframework.util.MultiValueMap; import org.springframework.validation.BindingResult; import org.springframework.validation.Errors; import org.springframework.web.method.HandlerMethod; @@ -70,6 +76,11 @@ public class PrintingResultHandler implements ResultHandler { this.printer.printHeading("Handler"); printHandler(result.getHandler(), result.getInterceptors()); + if (ClassUtils.hasMethod(ServletRequest.class, "startAsync")) { + this.printer.printHeading("Async"); + printAsyncResult(result); + } + this.printer.printHeading("Resolved Exception"); printResolvedException(result.getResolvedException()); @@ -87,11 +98,11 @@ public class PrintingResultHandler implements ResultHandler { protected void printRequest(MockHttpServletRequest request) throws Exception { this.printer.printValue("HTTP Method", request.getMethod()); this.printer.printValue("Request URI", request.getRequestURI()); - this.printer.printValue("Parameters", request.getParameterMap()); + this.printer.printValue("Parameters", getParamsMultiValueMap(request)); this.printer.printValue("Headers", getRequestHeaders(request)); } - protected static HttpHeaders getRequestHeaders(MockHttpServletRequest request) { + protected final HttpHeaders getRequestHeaders(MockHttpServletRequest request) { HttpHeaders headers = new HttpHeaders(); Enumeration names = request.getHeaderNames(); while (names.hasMoreElements()) { @@ -104,6 +115,24 @@ public class PrintingResultHandler implements ResultHandler { return headers; } + protected final MultiValueMap getParamsMultiValueMap(MockHttpServletRequest request) { + Map params = request.getParameterMap(); + MultiValueMap multiValueMap = new LinkedMultiValueMap(); + for (String name : params.keySet()) { + if (params.get(name) != null) { + for (String value : params.get(name)) { + multiValueMap.add(name, value); + } + } + } + return multiValueMap; + } + + protected void printAsyncResult(MvcResult result) throws Exception { + this.printer.printValue("Was async started", result.getRequest().isAsyncStarted()); + this.printer.printValue("Async result", result.getAsyncResult(0)); + } + /** Print the handler */ protected void printHandler(Object handler, HandlerInterceptor[] interceptors) throws Exception { if (handler == null) { @@ -178,7 +207,7 @@ public class PrintingResultHandler implements ResultHandler { this.printer.printValue("Cookies", response.getCookies()); } - protected static HttpHeaders getResponseHeaders(MockHttpServletResponse response) { + protected final HttpHeaders getResponseHeaders(MockHttpServletResponse response) { HttpHeaders headers = new HttpHeaders(); for (String name : response.getHeaderNames()) { headers.put(name, response.getHeaders(name)); diff --git a/spring-test-mvc/src/test/java/org/springframework/test/web/servlet/StubMvcResult.java b/spring-test-mvc/src/test/java/org/springframework/test/web/servlet/StubMvcResult.java index 6fb0e444d4b..c86e2901371 100644 --- a/spring-test-mvc/src/test/java/org/springframework/test/web/servlet/StubMvcResult.java +++ b/spring-test-mvc/src/test/java/org/springframework/test/web/servlet/StubMvcResult.java @@ -124,4 +124,8 @@ public class StubMvcResult implements MvcResult { return null; } + public Object getAsyncResult(long timeout) { + return null; + } + } diff --git a/spring-test-mvc/src/test/java/org/springframework/test/web/servlet/samples/standalone/AsyncTests.java b/spring-test-mvc/src/test/java/org/springframework/test/web/servlet/samples/standalone/AsyncTests.java index 4ef7ce93355..0a22f71ac09 100644 --- a/spring-test-mvc/src/test/java/org/springframework/test/web/servlet/samples/standalone/AsyncTests.java +++ b/spring-test-mvc/src/test/java/org/springframework/test/web/servlet/samples/standalone/AsyncTests.java @@ -17,6 +17,7 @@ package org.springframework.test.web.servlet.samples.standalone; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.asyncDispatch; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.request; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; @@ -59,11 +60,13 @@ public class AsyncTests { @Test public void testCallable() throws Exception { MvcResult mvcResult = this.mockMvc.perform(get("/1").param("callable", "true")) + .andDo(print()) .andExpect(request().asyncStarted()) .andExpect(request().asyncResult(new Person("Joe"))) .andReturn(); this.mockMvc.perform(asyncDispatch(mvcResult)) + .andDo(print()) .andExpect(status().isOk()) .andExpect(content().contentType(MediaType.APPLICATION_JSON)) .andExpect(content().string("{\"name\":\"Joe\",\"someDouble\":0.0,\"someBoolean\":false}"));