用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*/); } });