用 Mockito 调用回调

我有密码

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

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

47144 次浏览

您需要设置一个执行此操作的 Answer对象 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)

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

考虑使用 捕获者,它在任何情况下都更接近于“抓取[ 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]转换为所需的数据类型。它还要求您从 WITHIN the Response 中对系统的预回调状态做出任何断言,这意味着您的 Response 可能会扩大大小和范围。

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

如果你有这样的方法:

public void registerListener(final IListener listener) {
container.registerListener(new IListener() {
@Override
public void beforeCompletion() {
}


@Override
public void afterCompletion(boolean succeeded) {
listener.afterCompletion(succeeded);
}
});
}

然后按照下面的方法,你可以很容易地模仿上面的方法:

@Mock private IListener listener;


@Test
public void test_registerListener() {
target.registerListener(listener);


ArgumentCaptor<IListener> listenerCaptor =
ArgumentCaptor.forClass(IListener.class);


verify(container).registerListener(listenerCaptor.capture());


listenerCaptor.getValue().afterCompletion(true);


verify(listener).afterCompletion(true);
}

我希望这可以帮助某些人,因为我花了很多时间来解决这个问题。