Lukas Krecan opened SPR-17543 and commented
Let's take the following test of an asynchronous API
MvcResult mvcResult = mockMvc.perform(post("/asyncEndpoint")
.andExpect(status().isOk()) // passes but should not
.andReturn();
mockMvc.perform(asyncDispatch(mvcResult))
.andExpect(status().isConflict()); // the real status
We execute the request and check the status at once. Surprisingly it passes, even if the result is not ready yet and the final status will be different. I would except first .andExpect(status().isOk())
to fail since the result has not yet arrived (IllegalStateException?).
It's especially surprising if you forget that you have to test async controllers differently. Then you spend nontrivial amount of time investigating why your controller is returning 200 when you expect it to return an error.
Affects: 5.1.2
Comment From: spring-projects-issues
Rossen Stoyanchev commented
I see your point but I'm afraid there isn't anything we can do to fail proactively at that point. In MockHttpServletResponse
and in the Servlet API, the status is 200 from the very start by default, and technically it can change multiple times up until when the response is committed. So the only way to fail proactively at the point of "passes but should not" is to know that this is the end of the test, and that an async dispatch will not be performed. Aside from that the status is 200 (OK) at that point of the processing. It's not too hard to imagine a test verifying the status before vs after the async dispatch.
As far as spending a lot of time, the print()
feature should have helped to point out the issue:
MockHttpServletRequest:
HTTP Method = GET
Request URI = /1
Parameters = {deferredResult=[true]}
Headers = {}
Body = <no character encoding set>
Session Attrs = {}
Handler:
Type = org.springframework.test.web.servlet.samples.standalone.AsyncTests$AsyncController
Method = public org.springframework.web.context.request.async.DeferredResult<org.springframework.test.web.Person> org.springframework.test.web.servlet.samples.standalone.AsyncTests$AsyncController.getDeferredResult()
Async:
Async started = true
Async result = null
Resolved Exception:
Type = null
...
Comment From: snicoll
Closing based on the comment above.