gpt4 book ai didi

java - 没有从测试用例中调用 Spring DeferredResult onCompletion

转载 作者:塔克拉玛干 更新时间:2023-11-03 04:37:08 25 4
gpt4 key购买 nike

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

我维护一个 MapDeferredResult 和请求中收到的相应 ID。当 id 的计算在消费者线程中完成时,我在 Map 中检查此 id 并设置关联的 DeferredResults setResult 发送响应返回给客户端。

Controller 方法中,我有一个 DeferredResultonCompletion 回调,它从 map

然后客户端从它的请求中删除这个 id 并发送剩余的 id。例如,客户端发送最初的 id“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 秒超时并立即返回导致 result 。我读到了它,建议是将 .andExpect(request().asyncResult("Expected output")) 添加到 mockMvc 对象。

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

最佳答案

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

如果您查看评论,您可以在不更新的情况下解决它

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

关于java - 没有从测试用例中调用 Spring DeferredResult onCompletion,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39909996/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com