web-dev-qa-db-ja.com

最初の呼び出しのシミュレーションは失敗し、2番目の呼び出しは成功します

Mockitoを使用して、以下の(簡略化された)コードをテストします。 Mockitoに最初に失敗してから2回目に成功するように指示する方法がわかりません。

for(int i = 1; i < 3; i++) {
  String ret = myMock.doTheCall();

  if("Success".equals(ret)) {
    log.write("success");
  } else if ( i < 3 ) {
    log.write("failed, but I'll try again. attempt: " + i);
  } else {
    throw new FailedThreeTimesException();
  }
}

私は成功テストをセットアップできます:

Mockito.when(myMock).doTheCall().thenReturn("Success");

そして、失敗テスト:

Mockito.when(myMock).doTheCall().thenReturn("you failed");

しかし、1回(または2回)失敗して成功した場合、どのようにテストできますか?

86
jb.

ドキュメント から:

同じメソッド呼び出しに対して異なる戻り値/例外を使用してスタブする必要がある場合があります。典型的なユースケースは、イテレータのモックです。 Mockitoのオリジナルバージョンには、単純なモッキングを促進するためのこの機能がありませんでした。たとえば、反復子の代わりに、反復可能または単にコレクションを使用できます。これらは、スタブの自然な方法を提供します(たとえば、実際のコレクションを使用します)。まれなシナリオでは、連続した呼び出しをスタブすることが役立つ場合があります。

when(mock.someMethod("some arg"))
   .thenThrow(new RuntimeException())
  .thenReturn("foo");

//First call: throws runtime exception:
mock.someMethod("some arg");

//Second call: prints "foo"
System.out.println(mock.someMethod("some arg"));

だからあなたの場合、あなたがしたい:

when(myMock.doTheCall())
   .thenReturn("You failed")
   .thenReturn("Success");
200
Jon Skeet

欲しいものを書く最短の方法は

when(myMock.doTheCall()).thenReturn("Success", "you failed");

このようにthenReturnに複数の引数を指定すると、必要に応じて何度も使用される最後の引数を除き、各引数は最大で1回使用されます。たとえば、この場合、4回電話をかけると、「成功」、「失敗」、「失敗」、「失敗」が表示されます。

29

これに関連するコメントは読みにくいため、書式化された回答を追加します。

例外をスローするだけのvoid関数を使用してこれを実行し、その後に動作なしのステップを実行しようとする場合、次のようになります。

Mockito.doThrow(new Exception("MESSAGE"))
            .doNothing()
            .when(mockService).method(eq());
14
anoneironaut

this および this の回答に追加するには、ループを使用して、模擬呼び出しをチェーンすることもできます。これは、同じものを数回モックする必要がある場合、または何らかのパターンでモックする必要がある場合に便利です。

例(ファーフェッチはされていますが):

import org.mockito.stubbing.Stubber;

Stubber stubber = doThrow(new Exception("Exception!"));
for (int i=0; i<10; i++) {
    if (i%2 == 0) {
        stubber.doNothing();
    } else {
        stubber.doThrow(new Exception("Exception"));
    }
}
stubber.when(myMockObject).someMethod(anyString());
1
typoerrpr

別の状況があります。最初の呼び出しでvoid関数をモックし、2回目の呼び出しで正常に実行したかったのです。

これは私のために働く:

Mockito.doThrow(new RuntimeException("random runtime exception")).doCallRealMethod().when(object).method(Mockito.any());
0