【问题标题】:Spring MVC unit test for DeferredResult doesn't call timeout callbackDeferredResult 的 Spring MVC 单元测试不调用超时回调
【发布时间】:2018-07-27 00:05:13
【问题描述】:

我在 Java 7 上使用 Spring 4.3.18 和 Spring Boot 1.5.14。

我正在实现一个 RestController 端点,它返回一个带有超时回调的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 上的超时处理程序?

【问题讨论】:

    标签: java spring-mvc spring-test-mvc


    【解决方案1】:

    似乎可以像这样在单元测试中创建合成超时:

    @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()

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-02-16
      • 2015-01-15
      • 1970-01-01
      • 2017-05-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-03-19
      相关资源
      最近更新 更多