web-dev-qa-db-ja.com

Mockitoでスパイメソッドをモックする

次のようなFizzConfiguratorクラスの単体テストを作成しています。

_public class FizzConfigurator {
    public void doFoo(String msg) {
        doWidget(msg, Config.ALWAYS);
    }

    public void doBar(String msg) {
        doWidget(msg, Config.NEVER);
    }

    public void doBuzz(String msg) {
        doWidget(msg, Config.SOMETIMES);
    }

    public void doWidget(String msg, Config cfg) {
        // Does a bunch of stuff and hits a database.
    }
}
_

doWidget(String,Config)メソッドをスタブ化する簡単な単体テストを記述したいのですが(実際には起動せず、データベースにヒットしません)、これによりverifyができますdoBuzz(String)を呼び出すと、doWidgetが実行されます。 Mockitoは、ここでの仕事に適したツールのようです。

_public class FizzConfiguratorTest {
    @Test
    public void callingDoBuzzAlsoCallsDoWidget() {
        FizzConfigurator fixture = Mockito.spy(new FizzConfigurator());
        Mockito.when(fixture.doWidget(Mockito.anyString(), Config.ALWAYS)).
            thenThrow(new RuntimeException());

        try {
            fixture.doBuzz("This should throw.");

            // We should never get here. Calling doBuzz should invoke our
            // stubbed doWidget, which throws an exception.
            Assert.fail();
        } catch(RuntimeException rte) {
            return; // Test passed.
        }
    }
}
_

これはらしい(少なくとも私にとっては)良いゲームプランのようです。しかし、実際にコードを記述しようとすると、テストメソッド内の2行目(Mockito.when(...)行)で次のコンパイラエラーが発生します。

Mockito型のwhen(T)メソッドは引数に適用できません(void)

Mockitoがvoidを返すメソッドをモックできないことがわかりました。だから私は尋ねます:

  1. このテスト設定に正しくアプローチしていますか?または、doBuzzが内部でdoWidgetを呼び出す、より良い、Mockito推奨のテスト方法はありますか?そして
  2. doWidgetクラス全体の中で最も重要なメソッドであるため、FizzConfiguratorのモック/スタブについて何ができますか?
10
user1768830

これをテストするために例外を使用するのではなく、検証を使用します。もう1つの問題は、voidを返すメソッドでwhen()を使用できないことです。

ここに私がそれをする方法があります:

FizzConfigurator fixture = Mockito.spy(new FizzConfigurator());
doNothing().when(fixture).doWidget(Mockito.anyString(), Mockito.<Config>any()));
fixture.doBuzz("some string");
Mockito.verify(fixture).doWidget("some string", Config.SOMETIMES);
24
JB Nizet

これは、doWidgetメソッドがFizzConfiguratorが依存する別のクラスに属すべきであることを明確に示しています。

テストでは、この新しい依存関係はモックであり、そのメソッドがverifyで呼び出されたかどうかを簡単に確認できます。

0
rafaelportela

私の場合、スタブを作成しようとしていた方法で、誤ったマッチャーを渡していました。

私のメソッドシグネチャ(スタブしようとしていたスーパークラスメソッドの場合):文字列、オブジェクト。

私は通りました:

myMethod("string", Mockito.nullable(ClassType.class))および取得:

Hints: 1. missing thenReturn() 2. you are trying to stub a final method, which is not supported 3: you are stubbing the behaviour of another mock inside before 'thenReturn' instruction if completed

別のパラメーターでマッチャーを使用する場合は、文字列にもマッチャーを使用する必要があります。

myMethod(eq("string"), Mockito.nullable(ClassType.class))

お役に立てれば!

0
Adrian Elder