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


119

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回)失敗し、その後成功した場合、どうすればテストできますか?

回答:


250

ドキュメントから:

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

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");

25
これは、voidメソッドを処理する私のシナリオの正しい方向(ありがとう)を示しました-その場合、代替のスタイルを使用する必要があります...doThrow(new RuntimeException()).doNothing().when(myMock).doTheCall();
haggisandchips

38

あなたが望むものを書くための最短の方法は

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

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


22

これに関連するコメントは読みにくいので、フォーマットされた回答を追加します。

void例外をスローする関数を使用してこれを実行し、その後に動作なしの手順を実行する場合は、次のようにします。

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

4

これこの答えに追加するには、ループを使用してモックされた呼び出しを連鎖させることもできます。これは、同じものを何度も模擬する必要がある場合や、あるパターンで模擬する必要がある場合に便利です。

例(抜粋されたものですが):

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。
Mihai Morcov 2018

voidメソッドの呼び出しが必要な場合は、これが正しい答えになるはずです。
db80

4

私は別の状況でvoid、最初の呼び出しの関数をモックして、2番目の呼び出しで通常どおりに実行したいと思っていました。

これは私にとってはうまくいきます:

Mockito.doThrow(new RuntimeException("random runtime exception"))
       .doCallRealMethod()
       .when(spy).someMethod(Mockito.any());
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.