用于DeferredResult的Spring MVC单元测试不会调用超时回调 [英] Spring MVC unit test for DeferredResult doesn't call timeout callback
问题描述
我正在Java 7上使用Spring 4.3.18和Spring Boot 1.5.14.
I'm using Spring 4.3.18 and Spring Boot 1.5.14 on Java 7.
我正在实现RestController端点,该端点返回带有超时回调的DeferredResult
.我正在尝试为超时回调编写单元测试,但无法获得MockMvc
单元测试来调用超时回调.
I'm implementing a RestController endpoint which returns a DeferredResult
with a timeout callback. I'm trying to write a unit test for the timeout callback, but I can't get a MockMvc
unit test to call the timeout callback.
为了测试,我写了这个端点:
For the sake of testing, I wrote this endpoint:
@PostMapping("/test")
public DeferredResult<String>
testit() {
logger.info("testit called");
final DeferredResult<String> rv = new DeferredResult<>(1000L);
rv.onTimeout(new Runnable() {
@Override
public void run() {
logger.info("run called");
rv.setResult("timed out");
}
});
return rv;
}
和此单元测试:
@Autowired
private MockMvc mockMvc;
@Test
public void testTest() throws Exception {
MvcResult result = mockMvc.perform(post("/rest/tasks/test"))
.andExpect(request().asyncStarted())
.andReturn();
result.getAsyncResult(1500);
mockMvc.perform(asyncDispatch(result))
.andExpect(status().isOk())
;
}
(对result.getAsyncResult(1500)
的调用基于 https://jira.spring.io/browse/SPR-16869 )
运行此命令时,会调用testit()
端点,并且在1500 ms延迟后,我收到一个异常,抱怨从未调用setResult()
.超时处理程序未调用:
When I run this, the testit()
endpoint is called, and after a 1500 ms delay, I get an exception complaining that setResult()
was never called. The timeout handler isn't invoked:
java.lang.IllegalStateException: Async result for handler [public org.springframework.web.context.request.async.DeferredResult<java.lang.String> my.package.TasksController.testit()] was not set during the specified timeToWait=1500
at org.springframework.test.web.servlet.DefaultMvcResult.getAsyncResult(DefaultMvcResult.java:135)
at my.package.TasksControllerTest.testTest(TasksControllerTest.java:200)
2517 [main] INFO my.package.TasksController - testit called
MockHttpServletRequest:
HTTP Method = POST
Request URI = /rest/tasks/test
Parameters = {}
Headers = {}
Handler:
Type = my.package.TasksController
Method = public org.springframework.web.context.request.async.DeferredResult<java.lang.String> my.package.TasksController.testit()
Async:
Async started = true
Async result = null
Resolved Exception:
Type = null
ModelAndView:
View name = null
View = null
Model = null
FlashMap:
Attributes = null
MockHttpServletResponse:
Status = 200
Error message = null
Headers = {}
Content type = null
Body =
Forwarded URL = null
Redirected URL = null
Cookies = []
4037 [Thread-2] INFO org.springframework.web.context.support.GenericWebApplicationContext - Closing org.springframework.web.context.support.GenericWebApplicationContext@6ea91f6: startup date [Thu Jul 26 19:44:31 EDT 2018]; root of context hierarchy
我该怎么做才能使测试框架在DeferredResult上调用超时处理程序?
What do I need to do to make the test framework invoke the timeout handler on the DeferredResult?
推荐答案
似乎可以在单元测试中创建一个合成超时,如下所示:
It seems it's possible to create a synthetic timeout in the unit test like this:
@Test
public void testTest() throws Exception {
MvcResult result = mockMvc.perform(post("/rest/tasks/test"))
.andExpect(request().asyncStarted())
.andReturn();
// Trigger a timeout on the request
MockAsyncContext ctx = (MockAsyncContext) result.getRequest().getAsyncContext();
for (AsyncListener listener : ctx.getListeners()) {
listener.onTimeout(null);
}
mockMvc.perform(asyncDispatch(result))
.andExpect(status().isOk())
;
}
访问请求的异步侦听器并调用onTimeout()
将导致调用DeferredRequest
的超时回调.
Accessing the request's async listeners and calling onTimeout()
will result in calling the DeferredRequest
's timeout callback.
我的问题中对result.getAsyncResult(1500)
的调用对于此测试是多余的,因为asyncDispatch()
仍会调用getAsyncResult()
.
The call to result.getAsyncResult(1500)
from my question is redundant for this test, because asyncDispatch()
will call getAsyncResult()
anyway.
这篇关于用于DeferredResult的Spring MVC单元测试不会调用超时回调的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!