Mockitoは引数に関係なくメソッドをスタブできますか?


302

Mockitoを使用して、いくつかのレガシーコードをテストしようとしています。

FooDao次のようにプロダクションで使用されるaをスタブ化したい:

foo = fooDao.getBar(new Bazoo());

私は書くことができます:

when(fooDao.getBar(new Bazoo())).thenReturn(myFoo);

しかし、明らかな問題は、メソッドをスタブしたオブジェクトとgetBar()同じBazooオブジェクトで呼び出されないことです。(そのnewオペレーターを呪いなさい!)

myFoo引数に関係なくメソッドが返されるようにメソッドをスタブできたら、私はそれを気に入っています。それができない場合は、他の回避策の提案に耳を傾けますが、妥当なテストカバレッジが得られるまで、実稼働コードを変更しないようにしたいと思います。

回答:


456
when(
  fooDao.getBar(
    any(Bazoo.class)
  )
).thenReturn(myFoo);

または(nulls を避けるため):

when(
  fooDao.getBar(
    (Bazoo)notNull()
  )
).thenReturn(myFoo);

マッチャーをインポートすることを忘れないでください(他にもたくさんあります):

Mockito 2.1.0以降の場合:

import static org.mockito.ArgumentMatchers.*;

古いバージョンの場合:

import static org.mockito.Matchers.*;

2
回答が「回答のフリーズを受け入れる」の終わりに先行するとき、私はそれが大好きです。
Eric Wilson、

10
ありますnotNull(Bazoo.class)だけのようなany(Bazoo.class)(多分それはこの回答の時点で存在しなかった)
Dandreアリソン

2
私は2つの可能な引数のいずれかを持つことができる、BazooまたはCazooどちらもたとえばのサブクラスである、少し特殊な状況にありましたAzoo。以下のためにBazoo私は返すために必要なfoo、しかし、のためにCazoo、私は返すために必要なbar。この状況では、提案されたMatchers.any()ソリューションは機能しませんが、Matchers.isA()完全に機能します。
Tanvir 2014

3
org.mockito.Matchersは非推奨になりました- org.mockito.ArgumentMatchers代わりに使用してimport static org.mockito.ArgumentMatchers.*ください(例:docsを参照)
DontDivideByZero 2017年

when(myFoo.knowsWhatsUp()).thenReturn(myMoney);

18

次のように使用します。

when(
  fooDao.getBar(
    Matchers.<Bazoo>any()
  )
).thenReturn(myFoo);

インポートする前に Mockito.Matchers


1
これは低価格です!
DrB 2018年

15

http://site.mockito.org/mockito/docs/1.10.19/org/mockito/Matchers.html

anyObject() あなたのニーズに合うはずです。

また、あなたは常に実装を検討することが可能hashCode()equals()するためにBazooクラス。これにより、コード例が希望どおりに機能します。


2番目の提案には同意しますが、技術的でない理由により、これを行わないことを選択します。
Eric Wilson、

1
Matchersクラスは廃止されました(ドキュメント - 「このクラスはバージョン3.0で削除される可能性があります」
Johannes Rabauer

1

別のオプションは、古き良きファッションequals方法に依存することです。長期に引数としてとしてwhenモックequalsコード内の引数がテストされ、その後、Mockitoモックと一致します。

ここに例があります。

public class MyPojo {

    public MyPojo( String someField ) {
        this.someField = someField;
    }

    private String someField;

    @Override
    public boolean equals( Object o ) {
        if ( this == o ) return true;
        if ( o == null || getClass() != o.getClass() ) return false;
        MyPojo myPojo = ( MyPojo ) o;
        return someField.equals( myPojo.someField );
    }

}

次に、値がどうなるかがわかっていると仮定してsomeField、次のようにモックできます。

when(fooDao.getBar(new MyPojo(expectedSomeField))).thenReturn(myFoo);

長所:これはanyマッチャーよりも明示的です。コードのレビュー担当者として、私はコードのany初心者向けの開発者が書いているコードのロジックに目を通し、渡されている適切なオブジェクトを生成します。

con:オブジェクトに渡されるフィールドがランダムなIDである場合があります。この場合、モックコードで期待される引数オブジェクトを簡単に構築することはできません。

別の可能なアプローチはAnswerwhenメソッドで使用できるMockitoのオブジェクトを使用することです。 Answer実際の呼び出しをインターセプトして入力引数を検査し、モックオブジェクトを返すことができます。以下の例でanyは、モックされているメソッドへのリクエストをキャッチするために使用しています。しかし、Answerラムダで、Bazoの引数をさらに詳しく調べます。適切なIDが渡されたことを確認するためです。私はこれよりも、これを好むanyので、少なくともいくつかの検査が議論に対して行われます。

    Bar mockBar = //generate mock Bar.

    when(fooDao.getBar(any(Bazo.class))
    .thenAnswer(  ( InvocationOnMock invocationOnMock) -> {
        Bazo actualBazo = invocationOnMock.getArgument( 0 );

        //inspect the actualBazo here and thrw exception if it does not meet your testing requirements.
        return mockBar;
    } );

まとめると、私はequals(期待される引数と実際の引数が互いに等しいはずである)に依存するのが好きで、(実際の引数の状態を予測できないため)等しいことが不可能な場合は、Answer引数を検査します。

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