web-dev-qa-db-ja.com

@RunWith(MockitoJUnitRunner.class)vs MockitoAnnotations.initMocks(this)

新しいjUnit4テストの作成中に、@ RunWith(MockitoJUnitRunner.class)を使用するか、またはMockitoAnnotations.initMocks(this)を使用するかどうか疑問に思っています。

新しいテストを作成し、ウィザードはランナーで自動的にテストを生成しました。 MockitoJUnitRunnerのJavadocは次のように述べています。

JUnit 4.4以降と互換性があるこのランナーは、次の動作を追加します。

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

Runnerを使用することが、過去に使用していたinitMocks()メソッドよりも有利であるかどうかは明確ではありません。

ご意見やリンクは大歓迎です!

95
OceanBlue

MockitoJUnitRunnerは、フレームワークの使用状況の自動検証と、自動initMocks()を提供します。

フレームワークの使用状況の自動検証は、実際に持つ価値があります。これらの間違いのいずれかを行うと、レポートが改善されます。

  • 静的whenメソッドを呼び出しますが、一致するthenReturnthenThrow、またはthenでスタブを完了しないでください。 (以下のコードのエラー1)

  • モックでverifyを呼び出しますが、検証しようとしているメソッド呼び出しを提供することを忘れてください。 (以下のコードのエラー2)

  • whendoReturn、またはdoThrowの後にdoAnswerメソッドを呼び出してモックを渡しますが、スタブしようとしているメソッドの提供を忘れます。 (以下のコードのエラー3)

フレームワークの使用方法の検証がない場合、これらの間違いはfollowing 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チームは新しい機能を追加しました。これはMockitoJUnitRunnerとまったく同じ機能を実行するJUnitルールです。しかし、他のランナーの使用を妨げないため、より良いです。

含める

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

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

119

ランナーを使用すると、コーディングを少し節約できます(@Beforeメソッドは不要です)。一方、ランナーを使用できない場合があります。つまり、 SpringJUnit4ClassRunner のように既に使用している場合です。

それでおしまい。それは好みの問題です。

23