1. ホーム
  2. java

[解決済み] @RunWith(MockitoJUnitRunner.class) vs MockitoAnnotations.initMocks(this)

2022-06-16 17:43:04

質問

新しい jUnit4 テストを作成する際に、(1) (2) (3) (4) (5) (6)のいずれかを使用するかどうか悩んでいます。 @RunWith(MockitoJUnitRunner.class) を使うか、それとも MockitoAnnotations.initMocks(this) .

新しいテスト&を作成しました。ウィザードは自動的にRunnerを使ったテストを生成しました。MockitoJUnitRunnerのJavadocsには以下のように記載されています。

JUnit 4.4以降と互換性があり、このランナーには以下の動作が追加されます。

Mockでアノテーションされたモックを初期化するので、MockitoAnnotations.initMocks(Object)を明示的に使用する必要がありません。モックは各テストメソッドの前に初期化されます。 各テストメソッド終了後にフレームワークの使用状況を検証します。

Runnerを使うことで何か利点があるのかどうかは、私にはよくわかりません。 initMocks() メソッドよりも利点があるかどうかはわかりません。

どのように解決するのですか?

MockitoJUnitRunner は、フレームワークの使用に関する自動的な検証を行うだけでなく、自動的な initMocks() .

フレームワークの使用に関する自動検証は、実際に持つ価値があります。 このような間違いをした場合に、より良い報告をすることができます。

  • 静的な when メソッドを呼び出しますが、スタブには一致する thenReturn , thenThrow または then . (下記コードのエラー1)

  • あなたは verify を呼び出したが、検証しようとしているメソッドの呼び出しを忘れてしまった。 を提供するのを忘れています。 (以下のコードのエラー2)

  • を呼び出すと when メソッドの後に doReturn , doThrow または doAnswer でモックを渡しますが、スタブしようとしているメソッドを指定するのを忘れてしまいます。 を渡すことはできません。 (以下のコードのエラー3)

フレームワークの使用状況を検証していない場合、これらのミスが報告されるのは に続く がMockitoのメソッドを呼び出すまで報告されません。 これは次のようになるかもしれません。

  • を同じテスト・メソッド内で使用する必要があります (下記のエラー 1 のように)。
  • を次のテストメソッドで実行します(下記のエラー2のような)。
  • 次のテストクラスで

もし、最後に実行したテストで発生した場合(下記のエラー3のように)、それらは全く報告されないでしょう。

これらのエラーの種類はそれぞれどのように見えるかを示しています。 ここでは、JUnitがこれらのテストをここに記載されている順番で実行すると仮定しています。

@Test
public void test1() {

    // ERROR 1
    // This compiles and runs, but it's an invalid use of the framework because 
    // Mockito is still waiting to find out what it should do when myMethod is called.
    // But Mockito can't report it yet, because the call to thenReturn might 
    // be yet to happen.
    when(myMock.method1());

    doSomeTestingStuff();

    // ERROR 1 is reported on the following line, even though it's not the line with
    // the error.
    verify(myMock).method2();

}

@Test
public void test2() {

    doSomeTestingStuff();

    // ERROR 2
    // This compiles and runs, but it's an invalid use of the framework because
    // Mockito doesn't know what method call to verify.  But Mockito can't report 
    // it yet, because the call to the method that's being verified might 
    // be yet to happen.
    verify(myMock);
}

@Test
public void test3() {

    // ERROR 2 is reported on the following line, even though it's not even in 
    // the same test as the error.
    doReturn("Hello").when(myMock).method1();


    // ERROR 3
    // This compiles and runs, but it's an invalid use of the framework because
    // Mockito doesn't know what method call is being stubbed.  But Mockito can't 
    // report it yet, because the call to the method that's being stubbed might 
    // be yet to happen.

    doReturn("World").when(myMock);

    doSomeTestingStuff(); 

    //  ERROR 3 is never reported, because there are no more Mockito calls. 
}

さて、5年以上前に初めてこの回答を書いたとき、私はこう書きました。

ということで、私がお勧めするのは MockitoJUnitRunner を可能な限り使用することをお勧めします。 ただし、Tomasz Nurkiewiczが正しく指摘しているように、Springのような他のJUnitランナーが必要な場合は、これを使うわけにはいきません。

私の推奨は現在変更されています。 Mockitoチームは、私が最初にこの回答を書いてから、新しい機能を追加しました。 これはJUnitルールであり、その機能は MockitoJUnitRunner . しかし、他のランナーの使用を排除しないので、より優れています。

を含む。

@Rule 
public MockitoRule rule = MockitoJUnit.rule();

をテストクラスで使用します。 これはモックを初期化し、フレームワークの検証を自動化します; ちょうど MockitoJUnitRunner がそうであるように。 しかし、今、あなたは SpringJUnit4ClassRunner や他のJUnitRunnerと同様に使用できます。 Mockito 2.1.0以降では、どのような問題が報告されるかを正確に制御するオプションが追加されています。