web-dev-qa-db-ja.com

Mockito:引数に一致する呼び出しを待つ

私はSeleniumテストを作成して、mockitoでサーバーの動作を確認しています。具体的には、ボタンがクリックされたときに、ページコントローラーが、モックした依存関係の特定のメソッドを呼び出すようにしたいと思います。

これはSeleniumテストなので、モックが別のスレッドで呼び出されるのを待つ必要があるため、mockitoタイムアウトを使用しています。

verify(myMock, timeout(5000).times(1)).myMethod("expectedArg");

私が抱えている問題は、myMethodが何度も呼び出されることです...予期される引数に一致する呼び出しを待つのではなく、タイムアウトは最初の呼び出しを待つだけです。 timeout(50000)ではなくThread.sleep(50000)を使用すると、期待どおりに動作しますが、これはダーティなので、回避したいと考えています。

予想される入力でmyMethodが呼び出されるのをどのように待機しますか?

22
Bryan Hart

期待する呼び出しの固定数を設定できる場合は、ArgumentCaptorを使用して実行できます。

import static org.hamcrest.CoreMatchers.hasItem;

@Captor ArgumentCaptor<String> arg;

@Before
public void setUp() throws Exception {
    // init the @Captor
    initMocks(this);
}

@Test
public void testWithTimeoutCallOrderDoesntMatter() throws Exception {
    // there must be exactly 99 calls
    verify(myMock, timeout(5000).times(99)).myMethod(arg.capture());
    assertThat(arg.getAllValues(), hasItem("expectedArg"));
}

別の方法は、検証するすべての予期される値を指定することですが、それらは呼び出される正確な順序で提供される必要があります。上記のソリューションとの違いは、検証されていない引数を使用してモックがさらに呼び出されても、失敗しないことです。言い換えれば、呼び出しの総数を知る必要はありません。コード例:

@Test
public void testWithTimeoutFollowingCallsDoNotMatter() throws Exception {
    // the order until expected arg is specific
    verify(callback, timeout(5000)).call("firstExpectedArg");
    verify(callback, timeout(5000)).call("expectedArg");
    // no need to tell more, if additional calls come after the expected arg
    // verify(callback, timeout(5000)).call("randomArg");
}
22
juhoautio

これは非常にクリーンなソリューションではありませんが、あなたはこれを行うことができます(XXはここでは想定される戻り値の型です):

final CountDownLatch latch = new CountDownLatch(1);

doReturn(new Answer<XX>()
    {
        @Override
        public XX answer(InvocationOnMock invocation)
        {
            latch.countDown();
            return someInstanceOfXX;
        }
    }
).when(myMock).myMethod("expectedArg");

次に、メソッドが呼び出されたかどうかをテストするには、次のようにします。

try {
    assertTrue(latch.await(5L, TimeUnit.SECONDS));
} catch (InterruptedException e) {
    // Urgh... Failed. Deal with it and:
    Thread.currentThread.interrupt();
}
16
fge