使用 Mockito 调用回调

新手上路,请多包涵

我有一些代码

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

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

原文由 Kurru 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 630
2 个回答

您想要设置一个 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 替换为它应该是的任何东西)

原文由 Dawood ibn Kareem 发布,翻译遵循 CC BY-SA 3.0 许可协议

考虑使用 ArgumentCaptor ,它在任何情况下都更接近于“抓取 [bing] 回调对象”。

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

虽然 Answer 在回调需要立即返回时是个好主意(读取:同步),但它也引入了创建匿名内部类的开销,并且不安全地转换来自 invocation.getArguments()[n] 的元素 --- 到你想要的数据类型。它还要求您从 Answer 内部对系统的回调前状态做出任何断言,这意味着您的 Answer 的大小和范围可能会增加。

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

原文由 Jeff Bowman 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题