Spring DeferredResult 的 MVC 单元测试不调用超时回调
Spring MVC unit test for DeferredResult doesn't call timeout callback
我正在使用 Spring 4.3.18 和 Spring Boot 1.5.14 on Java 7.
我正在实施一个 RestController 端点,其中 returns 一个 DeferredResult
带有超时回调。我正在尝试为超时回调编写单元测试,但我无法获得 MockMvc
单元测试来调用超时回调。
为了测试,我写了这个端点:
@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 毫秒延迟后,我收到一个异常,抱怨 setResult()
从未被调用过。未调用超时处理程序:
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 上的超时处理程序?
似乎可以像这样在单元测试中创建一个综合超时:
@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
的超时回调。
我的问题中对 result.getAsyncResult(1500)
的调用对于此测试来说是多余的,因为 asyncDispatch()
无论如何都会调用 getAsyncResult()
。
我正在使用 Spring 4.3.18 和 Spring Boot 1.5.14 on Java 7.
我正在实施一个 RestController 端点,其中 returns 一个 DeferredResult
带有超时回调。我正在尝试为超时回调编写单元测试,但我无法获得 MockMvc
单元测试来调用超时回调。
为了测试,我写了这个端点:
@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 毫秒延迟后,我收到一个异常,抱怨 setResult()
从未被调用过。未调用超时处理程序:
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 上的超时处理程序?
似乎可以像这样在单元测试中创建一个综合超时:
@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
的超时回调。
我的问题中对 result.getAsyncResult(1500)
的调用对于此测试来说是多余的,因为 asyncDispatch()
无论如何都会调用 getAsyncResult()
。