【问题标题】:Spring DeferredResult onCompletion not called from test cases未从测试用例调用 Spring DeferredResult onCompletion
【发布时间】:2017-02-16 00:36:27
【问题描述】:

我有一个彗星(长轮询)Controller 调用,它接收一些 id 和 puts,然后如果没有对该 id 的计算正在运行,则进入阻塞队列,从Consumertake queue 并对这些 id 执行计算。我正在使用 Springs DeferredResult 来支持异步。

我维护DeferredResultMap 以及在请求中收到的相应ID。当消费者线程中的 id 计算完成后,我会在 Map 中检查此 id 并设置相关联的 DeferredResults setResult 将响应发送回客户端。

Controller 方法中,我有一个DeferredResultonCompletion 回调,它从Map 中删除了这个DeferredResult 对象。

然后客户端从它的请求中删除这个 id 并发送剩余的 id。例如说客户端最初发送 ids "1,2,3" 他们都被插入到BlockingQueue 并且说 id "2" 的计算已经完成了,然后它的DeferredResults setResult 将被设置,这将响应返回给客户端。通过回调,这个DeferredResult 将从Map 中删除。并且客户端在下一个请求中将发送 ids “1, 3”。

现在一切正常,但是当我开始为此编写测试用例时,从未调用过 onCompletion 回调。我什至在 springs 官方示例中尝试过它,即使在那里似乎也没有被调用。有没有办法调用它,或者我的实现中有什么不正确的地方。

这是我的Controller 方法:

@RequestMapping(value = "views/getLongPollingGraphData", method = RequestMethod.GET, headers = "Accept=application/json")
@ResponseBody
public DeferredResult<WebServiceResponse> getLongGraphData(
        HttpServletRequest request,
        @RequestParam(value = "ids") String ids) 
{
    //create a default response in case, when no result has been calculated till timeout
    WebServiceResponse awrDefault = new WebServiceResponse();

    //set time out this DeferredResult, after 5 seconds 
    final DeferredResult<WebServiceResponse> deferredResult = new DeferredResult<WebServiceResponse>(5000L, awrDefault);

    //logic to set in blocking queue
    //mMapOfDeferredResultAndViews.put(deferredResult, listOfViews.keySet());

    deferredResult.onCompletion(new Runnable() {
        @Override
        public void run() 
        {
            mMapOfDeferredResultAndViews.remove(deferredResult);
        }
    });

    return deferredResult;
}

下面是部分测试用例:

@Before
public void setup() 
{
    this.mockMvc = webAppContextSetup(this.wac).build();
}

@Test
public void testLongPollGraphData()
{
    try
    {         
        String ids = "22,23,25";
        List<Integer> idList = convertStringToList(ids);

        while(idList.size() > 0)
        {
            MvcResult mvcResult = this.mockMvc.perform(get("/views/getLongPollingGraphData")
                .contentType(MediaType.APPLICATION_JSON)
                .param("ids", ids)          
                .andReturn();

            this.mockMvc.perform(asyncDispatch(mvcResult));
            WebServiceResponse result = (WebServiceResponse)mvcResult.getAsyncResult();

            if(result != null)
            {
                EJSChartsData chartsData = (EJSChartsData)result.getResponse();
                if(chartsData != null && chartsData.getViewId() != -1)
                {
                    int viewId = chartsData.getViewId();
                    idList.remove((Integer)viewId);
                    ids = idList.toString().replace("[", "").replace("]", "");
                }
            }
        }
    }
    catch(Exception e)
    {
        fail(e.toString());
    }
}

Controller 方法被调用,我收到了预期的响应,但由于onCompletion 回调从未被调用,我通过删除 id 再次调用该方法的逻辑受到了打击,因为Map 保持在过去DeferredResult

更新

测试类注解为:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = { "/test-context.xml" })
@WebAppConfiguration
@TransactionConfiguration(transactionManager = "transactionManager", defaultRollback = true)
@Transactional(readOnly = false, propagation = Propagation.REQUIRES_NEW)

我有另一个观察,对 getLongPollingGraphData 的调用没有完成,即它不等待指定的 5 秒超时并立即返回,导致 resultnull。我读过它,建议将.andExpect(request().asyncResult("Expected output")) 添加到mockMvc 对象。

但这是我测试用例的重点,我希望计算并返回结果,以便我可以根据收到的响应重新发送修改我的 ids 变量的请求。

【问题讨论】:

  • 在顶部显示您的测试类注释
  • @shazin 在问题中更新了一些额外的观察结果。
  • 您的 Web 应用程序使用 tomcat 吗?
  • @eg04lt3r 是的,我愿意。
  • @eg04lt3r 但是它和测试用例有什么关系呢?

标签: java spring spring-mvc asynchronous


【解决方案1】:

您使用的是哪个版本的 Spring? 我为类似的情况打开了SPR-13615,它在 4.2.3 中得到了修复(影响 4.2.2)。

如果您查看 cmets,您可以在不使用更新的情况下解决它

    mvcResult.getRequest().getAsyncContext().complete();

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-01-15
    • 2016-03-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-08-23
    • 1970-01-01
    相关资源
    最近更新 更多