私はいくつかのコードを持っています
service.doAction(request, Callback<Response> callback);
Mockito を使用してコールバック オブジェクトを取得し、callback.reply(x) を呼び出すにはどうすればよいですか
Answer
それを行うオブジェクトを設定します。https://static.javadoc.io/org.mockito/mockito-core/2.8.47/org/mockito/Mockito.html#answer_stubsにある Mockito のドキュメントを
ご覧ください。
あなたは次のようなものを書くかもしれません
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の使用を検討してください。これは、いずれの場合も「コールバックオブジェクトを取得する」に近いものです。
/**
* 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を使用して、サービスに渡されたCallbackオブジェクトをキャプチャします。これで、すべてのアサーションをテストメソッドレベルで作成し、必要に応じて呼び出すreply
ことができます。これは、サービスが複数の同時コールバックを担当している場合に特に役立ちます。これは、コールバックが返される順序をより細かく制御できるためです。
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*/);
}
});