未从测试用例

时间:2016-10-07 05:23:57

标签: java spring spring-mvc asynchronous

我有一个彗星(长轮询)Controller调用,如果puts没有运行该ID的计算,则会将一些ID和Consumer带入阻塞队列从takequeue并对这些ID执行计算。我正在使用Springs DeferredResult进行异步支持。

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

Controller方法中,我onCompletion回调了DeferredResult,从DeferredResult中移除了此Map个对象。

客户端然后从其请求中删除此ID并发送剩余的ID。例如,客户端发送最初的ID为“1,2,3”,它们都被插入到BlockingQueue中,并且表示id“2”的计算已提前完成,然后是DeferredResults {{1}将被设置,它将响应返回给客户端。通过回调,此setResult将从DeferredResult中移除。并且下一个请求中的客户端将发送ID“1,3”。

现在一切正常,但是当我开始为此编写测试用例时,永远不会调用Map回调。我甚至在泉水官方的例子中试过它,它似乎甚至没有被称为。有没有办法调用它,或者在我的实现中有些不正确的东西。

这是我的onCompletion方法:

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回调从未被调用,我通过删除id再次调用该方法的逻辑需要命中{{{ 1}}保留过去的onCompletion

更新

测试类注释是:

Map

我有另一个观察,对DeferredResult的调用未完成,即它不等待指定的5秒超时并立即返回,导致@RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(locations = { "/test-context.xml" }) @WebAppConfiguration @TransactionConfiguration(transactionManager = "transactionManager", defaultRollback = true) @Transactional(readOnly = false, propagation = Propagation.REQUIRES_NEW) getLongPollingGraphData。我读到了它,建议将result添加到null对象。

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

1 个答案:

答案 0 :(得分:0)

您使用的是哪个版本的Spring? 我已经为类似的案例打开SPR-13615,并在4.2.3(影响4.2.2)中得到修复。

如果您查看评论,可以使用

进行解决而无需更新
    mvcResult.getRequest().getAsyncContext().complete();