用Mockito调用callback

我有一些代码

service.doAction(request, Callback<Response> callback); 

我如何使用Mockito抓取callback对象,并调用callback.reply(x)

你想设置一个Answer对象来做到这一点。 看看Mockito文档,在https://static.javadoc.io/org.mockito/mockito-core/2.8.47/org/mockito/Mockito.html#answer_stubs

你可能会写些类似的东西

 when(mockService.doAction(any(Request.class), any(Callback.class))).thenAnswer( new Answer<Object>() { Object answer(InvocationOnMock invocation) { ((Callback<Response>) invocation.getArguments()[1]).reply(x); return null; } }); 

(当然,用它应该是的x代替)

考虑使用一个ArgumentCaptor ,它在任何情况下都更接近于“抓住callback对象”。

 /** * Captor for Response callbacks. Populated by MockitoAnnotations.initMocks(). * You can also use ArgumentCaptor.forClass(Callback.class) but you'd have to * cast it due to the type parameter. */ @Captor ArgumentCaptor<Callback<Response>> callbackCaptor; @Test public void testDoAction() { // Cause service.doAction to be called // Now call callback. ArgumentCaptor.capture() works like a matcher. verify(service).doAction(eq(request), callbackCaptor.capture()); assertTrue(/* some assertion about the state before the callback is called */); // Once you're satisfied, trigger the reply on callbackCaptor.getValue(). callbackCaptor.getValue().reply(x); assertTrue(/* some assertion about the state after the callback is called */); } 

当callback需要立即返回(同步读取)时, Answer是一个好主意,同时也引入了创build匿名内部类的开销,并且将元素从invocation.getArguments()[n]不安全地转换为数据types你要。 它还要求您在答案中做出有关系统预callback状态的任何断言,这意味着您的答案可能会在规模和范围上扩大。

相反,请asynchronous处理您的callback:使用ArgumentCaptor捕获传递给您的服务的Callback对象。 现在,您可以在testing方法级别进行所有的断言,并在您select时调用reply 。 如果您的服务负责多个同时callback,这是特别有用的,因为您可以更好地控制callback的返回顺序。

 when(service.doAction(any(Request.class), any(Callback.class))).thenAnswer( new Answer() { Object answer(InvocationOnMock invocation) { Callback<Response> callback = (Callback<Response>) invocation.getArguments()[1]; callback.reply(/*response*/); } });