Mockito-doReturn()とwhen()の違い


196

現在、Mockitoを使用して、コントローラーメソッドをテストするSpring MVCアプリケーションのサービスレイヤーオブジェクトをモックしています。ただし、Mockitoの詳細を読んでいると、メソッドdoReturn(...).when(...)がと同等であることがわかりましたwhen(...).thenReturn(...)。だから、私の質問には微妙な違い何で同じことを行うか、二つの方法持つのポイント何ですdoReturn(...).when(...)when(...).thenReturn(...)

任意の助けいただければ幸いです。


1
javadocには、doReturn()役立ついくつかのケースがあります。
Sotirios Delimanolis 2013

5
主な違いの1つは、doReturn(...)。when(..)が古いものであり、タイプセーフではないため、コンパイラーがキャストについて不平を言っているときに使用できることです。とき(..)thenReturn(..)は型の安全性の面ではるかに優れています。
user2511882

回答:


227

スタブの2つの構文はほぼ同じです。ただし、スタブにはいつでも使用できdoReturn/whenます。ただし、使用できない場合がありますwhen/thenReturn。voidメソッドのスタブはその1つです。その他には、Mockitoスパイの使用や、同じ方法を複数回スタブすることが含まれます。

一つのことwhen/thenReturnあなたを与える、doReturn/whenしませんが、あなたはコンパイル時に、戻っていることを値の型チェックです。ただし、これはほとんど価値がないと思います。タイプが間違っている場合は、テストを実行するとすぐにわかります。

のみを使用することを強くお勧めしdoReturn/whenます。2つの構文を学習しても意味はありません。

私の回答をForming Mockitoの「文法」で参照することをお勧めします。これは、非常に密接に関連する質問に対するより詳細な回答です。


16
私はデイビッドに少し同意しません。私はよく使用時に間違ったタイプを返し、doReturn/when何がうまくいかないかを理解するために次の数分を費やす状況に出くわします。コンパイル型の型チェックは、で非常に役立ちwhen/thenReturnます。
Saket 2016

11
Mockito when/thenReturnでは、の代わりにuseを使用することをお勧めしますdoReturn/when
CodyEngel 2017

2
@CodyEngelと私がここで私の回答とstackoverflow.com/q/11462697で概説した以外に、そのような推奨の理由はありません。数年前、私は現在Mockitoの主任開発者を務めているBrice Dutheilとこれについて話し合いました、そして私の記憶の中で、彼は同意します。私は彼にここにコメントを投稿するように頼みます(彼がそうすることを保証するものではありません)。
Dawood ibnカリーム2017

18
javadocツールの状態doReturn/whenのトレードオフです。チームはwhen/then何らかの方法を推奨しませんが、このアプローチはより直感的で読みやすく、コンパイル時間チェックを提供します。これは、Mockitoを普及させて使いやすくしたアプローチです。コードベースがチームのさまざまなスキルセット。まだそれはスパイと無効な方法に関して欠点があります。
Brice

5
参考までに:メソッド呼び出しのYODAスタイルのコーディングに変わるdoReturn()という大きな欠点があります。それが後で最初に書き留められます。ほとんどの人は左から右に読みます。したがって、頭の中でreturn-whenロジックを逆にすることを常に覚えておく必要があります。
GhostCat 2017

199

@Spyモック(で注釈された)の代わりにスパイされたオブジェクト(で注釈された)を使用する場合、両方のアプローチは異なる動作をします@Mock

  • when(...) thenReturn(...) 指定された値が返される直前に実際のメソッド呼び出しを行います。したがって、呼び出されたメソッドが例外をスローする場合は、それに対処する/モックするなどする必要があります。もちろん、結果(で定義したものthenReturn(...))は引き続き得られます

  • doReturn(...) when(...) メソッドをまったく呼び出さない

例:

public class MyClass {
     protected String methodToBeTested() {
           return anotherMethodInClass();
     }

     protected String anotherMethodInClass() {
          throw new NullPointerException();
     }
}

テスト:

@Spy
private MyClass myClass;

// ...

// would work fine
doReturn("test").when(myClass).anotherMethodInClass();

// would throw a NullPointerException
when(myClass.anotherMethodInClass()).thenReturn("test");

37
この動作は実際のオブジェクトの「ラッパー」であるため、スパイされたオブジェクトに対してのみ機能します。モックされたオブジェクトの場合、それがwhen / thenReturnまたはdoReturn / whenであるかどうかは関係ありません。モックされたオブジェクトが実際のメソッドを呼び出すことはありません。
RafaelOrágio15年

この機能を使用する必要がある理由を詳しく教えてください。実用的な事例は見当たりません。テストの目的は、さまざまなユースケースでコードが正しいことを確認することです。メソッドの呼び出しが例外をスローする場合、テストは例外をスローする必要があり、値を返さない
Gleichmut

@Gleichmutこれは架空のシナリオで、doReturnの使用法と利点を示しています。実際のアプリケーションでは、単に例外を返すメソッドは、もちろん無意味でます..しかし、あなたは...特定の条件で例外をスローすることがあり(このような、おそらく非常に薄いない)方法持っている
akcasoy

1
明確にするために:when()。thenReturn()メソッドは実際のメソッド(スパイの-モックには関係ありません)を一度だけ呼び出します。これは、モックの動作を指定する行で発生します(when(myClass.anotherMethodInClass() .thenRet ...)。その後、実際のメソッドが再度呼び出されることはありません。説明を読むときに、いくつかのデコレータロジックが予期されているかどうかを確認するとよいでしょう。上
Jonas

これはの利点のようには見えませんdoReturn()。ライブラリの乱用のように見えます。純粋なモックの代わりにスパイのポイントは、実際の呼び出しを利用することです。彼らはまた、次のようにスパイを使用しないよう警告します:github.com/mockito/mockito/wiki/Using-Spies- (and -Fakes)(およびクラスを拡張してメソッドをオーバーライドすることをお勧めします)
Matthew Read

13

Mockito.when(Object)を使用できないまれな場合に、Mockito javadoc doReturn()when()Use doReturn()の代わりに使用する理由を説明しているようです。

Mockito.when(Object)は引数のタイプセーフで読みやすいため(特に連続した呼び出しをスタブする場合)、スタブには常に推奨されることに注意してください。

doReturn()が便利になるまれなケースを以下に示します。

1.実際のオブジェクトをスパイしてスパイで実際のメソッドを呼び出すと、副作用が発生する

List list = new LinkedList(); List spy = spy(list);

//不可能:実際のメソッドが呼び出されるため、spy.get(0)はIndexOutOfBoundsExceptionをスローします(リストはまだ空です)

when(spy.get(0)).thenReturn("foo");

//スタブにはdoReturn()を使用する必要があります: doReturn("foo").when(spy).get(0);

2.以前の例外スタブをオーバーライドします。

when(mock.foo()).thenThrow(new RuntimeException());

//不可能:例外スタブfoo()メソッドが呼び出されるため、RuntimeExceptionがスローされます。 when(mock.foo()).thenReturn("bar");

//スタブにはdoReturn()を使用する必要があります:

doReturn("bar").when(mock).foo(); 上記のシナリオは、Mockitoのエレガントな構文のトレードオフを示しています。ただし、シナリオは非常にまれです。スパイは散発的である必要があり、例外スタブのオーバーライドは非常にまれです。言うまでもなく、一般的にスタブをオーバーライドすることは、スタブが多すぎることを指摘する潜在的なコード臭です。


6

この答えを続けると、たとえば最初に呼び出されたとき、2回目に呼び出されたときなどにメソッドが異なる値を返すようにする場合は、たとえば値を渡すことができるという別の違いがあります...

PowerMockito.doReturn(false, false, true).when(SomeClass.class, "SomeMethod", Matchers.any(SomeClass.class));

そのため、同じテストケースでメソッドが呼び出されるとfalseを返し、その後再びfalseを返し、最後にtrueを返します。


弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.