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


118

新しいjUnit4テストを作成しているときに、@RunWith(MockitoJUnitRunner.class) またはMockitoAnnotations.initMocks(this)のどちらを使用するのか迷っています。

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

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

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

Runnerを使用することが、これまで使用してきたinitMocks()メソッドよりも優れているかどうかはわかりません。

どんな考えやリンクもいただければ幸いです!

回答:


147

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

フレームワークの使用状況の自動検証は実際に価値があります。これらのミスの1つを犯した場合、より適切なレポートが提供されます。

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

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

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

フレームワークの使用を検証していない場合、これらの誤りは、の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以降、報告される問題の種類を正確に制御する追加のオプションがあります。


絶対に同じだとは言えません。1つのテストケースで、junitランナーのセットアップが失敗し、initMocksのセットアップを行わない限り、モックが適切に挿入されません
dtc

testng 6.8.8 + mockito 1.10.19を使用しており、MockitoJUnitRunnerは使用できませんが、検証フレームワークは引き続き機能します。そして、それは@David Wallaceとまったく同じように機能します。誰かが説明できますか?これは、まだ@ Before *コールバックとMockitoAnnotations.initMocks(this)があるためですか?
yuranos 16

@ yuranos87新しい質問をする必要があるようです。コードを含めるときは忘れずに行ってください。コードを表示しないと、「なぜこのコードはXYZを行うのか」と質問するのは少し無意味です。
Dawood ibnカリーム2016

1
TestRunnerソリューションの使用は@Ruleよりもはるかに優れています
Rule

1
@alexandroid私の最善の提案は、を使用して独自の答えを書くことです@ExtendWith。それは本当に私が知っていることではありません。Stack Overflowの優れている点は、このような質問に対して、複数の正解が返される可能性があることです。
Dawood ibnカリーム

24

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

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


2
initMocks()行以外では、@ Beforeメソッドは他のセットアップでも必要ですよね?
OceanBlue 2012年

2
@OceanBlue:もちろん、ランナーに移行した後で@BeforeメソッドinitMocks()を保持する必要がある以外のメソッドが含まれている場合。
Tomasz Nurkiewicz

フレームワークの検証に関するDavid Wallaceの回答は私の質問に完全に回答するので、それを受け入れましたが、このランナーはSpringのような別のランナーと一緒に使用できないことを指摘して+1しました。ありがとう!
OceanBlue

1
私はSpring Bootを使用SpringJUnit4ClassRunnerしていますが、モックが自動的に初期化されます。普通の春はわかりません。
gustavohenke 2016年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.