@RunW (MitoUitRunner.class) vs MockitoAnnotations.init (ini)

118

Saat menulis pengujian jUnit4 baru, saya bertanya-tanya apakah akan menggunakan @RunWith (MockitoJUnitRunner.class) atau MockitoAnnotations.initMocks (ini) .

Saya membuat tes baru & wizard secara otomatis membuat tes dengan Runner. Javadocs untuk MockitoJUnitRunner menyatakan berikut ini:

Kompatibel dengan JUnit 4.4 dan lebih tinggi, pelari ini menambahkan perilaku berikut:

Menginisialisasi tiruan yang dianotasi dengan Mock, sehingga penggunaan MockitoAnnotations.initMocks (Object) secara eksplisit tidak diperlukan. Mock diinisialisasi sebelum setiap metode pengujian. memvalidasi penggunaan framework setelah setiap metode pengujian.

Tidak jelas bagi saya apakah menggunakan Runner memiliki keuntungan atas metode initMocks () yang telah saya gunakan di masa lalu.

Pikiran atau tautan apa pun akan dihargai!

Lautan biru
sumber

Jawaban:

147

MockitoJUnitRunnermemberi Anda validasi otomatis penggunaan kerangka kerja, serta otomatis initMocks().

Validasi otomatis penggunaan kerangka kerja sebenarnya layak untuk dimiliki. Ini memberi Anda pelaporan yang lebih baik jika Anda melakukan salah satu dari kesalahan ini.

  • Anda memanggil whenmetode statis , tetapi tidak menyelesaikan stubbing dengan pencocokan thenReturn, thenThrowatau then. (Kesalahan 1 pada kode di bawah)

  • Anda memanggil verifytiruan, tetapi lupa untuk memberikan panggilan metode yang Anda coba verifikasi. (Kesalahan 2 pada kode di bawah)

  • Anda memanggil whenmetode setelahnya doReturn, doThrowatau doAnswerdan melewatkan tiruan, tetapi lupa untuk memberikan metode yang Anda coba stub. (Kesalahan 3 pada kode di bawah)

Jika Anda tidak memiliki validasi penggunaan kerangka kerja, kesalahan ini tidak dilaporkan hingga panggilan berikut ke metode Mockito. Ini mungkin

  • dalam metode pengujian yang sama (seperti kesalahan 1 di bawah),
  • dalam metode pengujian berikutnya (seperti kesalahan 2 di bawah),
  • di kelas tes berikutnya.

Jika terjadi pada pengujian terakhir yang Anda jalankan (seperti kesalahan 3 di bawah), mereka tidak akan dilaporkan sama sekali.

Berikut tampilan setiap jenis kesalahan tersebut. Asumsikan di sini bahwa JUnit menjalankan pengujian ini dalam urutan yang tercantum di sini.

@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. 
}

Sekarang ketika saya pertama kali menulis jawaban ini lebih dari lima tahun yang lalu, saya menulis

Jadi saya akan merekomendasikan penggunaan MockitoJUnitRunnersedapat mungkin. Namun, seperti yang ditunjukkan Tomasz Nurkiewicz dengan benar, Anda tidak dapat menggunakannya jika Anda membutuhkan pelari JUnit lain, seperti pelari Musim Semi.

Rekomendasi saya sekarang telah berubah. Tim Mockito telah menambahkan fitur baru sejak saya pertama kali menulis jawaban ini. Ini adalah aturan JUnit, yang menjalankan fungsi yang persis sama dengan file MockitoJUnitRunner. Tapi itu lebih baik, karena tidak menghalangi penggunaan pelari lain.

Sertakan

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

di kelas pengujian Anda. Ini menginisialisasi tiruan, dan mengotomatiskan validasi kerangka kerja; seperti MockitoJUnitRunnerhalnya. Tapi sekarang, Anda bisa menggunakan SpringJUnit4ClassRunneratau JUnitRunner lainnya juga. Dari Mockito 2.1.0 dan seterusnya, ada opsi tambahan yang mengontrol secara tepat jenis masalah yang dilaporkan.

Dawood ibn Kareem
sumber
saya pasti tidak bisa mengatakan mereka sama. dalam satu kasus tes, setup JUnit pelari gagal untuk saya dan tidak menyuntikkan mengolok-olok saya dengan benar kecuali saya melakukan initMocks pengaturan
dtc
Kami menggunakan testng 6.8.8 + mockito 1.10.19 dan, jelas kami tidak dapat menggunakan MockitoJUnitRunner, tetapi kerangka validasi masih berfungsi! Dan berfungsi persis seperti @David Wallace. Bisakah seseorang menjelaskan? Apakah ini karena kita masih memiliki @ Before * callbacks dan MockitoAnnotations.initMocks (this)?
yuranos
@ yuranos87 Kedengarannya seperti sesuatu yang harus Anda tanyakan sebagai pertanyaan baru. Jangan lupa untuk memasukkan kode Anda ketika Anda melakukannya - tidak ada gunanya menanyakan "mengapa kode ini melakukan XYZ" jika Anda tidak menunjukkan kodenya.
Dawood ibn Kareem
1
menggunakan solusi TestRunner mengungguli @Rule sejauh ini
Aturan
1
@alexandroid Saran terbaik saya adalah agar Anda menulis jawaban Anda sendiri, menggunakan @ExtendWith. Itu bukanlah sesuatu yang saya ketahui. Hal hebat tentang Stack Overflow adalah pada pertanyaan seperti ini, Anda bisa mendapatkan beberapa jawaban yang benar.
Dawood ibn Kareem
24

Menggunakan runner memungkinkan Anda menghemat sedikit pengkodean (tidak perlu @Beforemetode). Di sisi lain, menggunakan runner terkadang tidak memungkinkan, yaitu jika Anda sudah menggunakan runner, seperti SpringJUnit4ClassRunner.

Itu dia. Ini hanya masalah preferensi.

Tomasz Nurkiewicz
sumber
2
Selain baris initMocks (), metode @Before masih diperlukan untuk penyiapan lain, bukan?
OceanBlue
2
@OceanBlue: Tentu saja jika @Beforemetode Anda berisi apa pun kecuali initMocks()Anda harus menyimpannya setelah bermigrasi ke pelari.
Tomasz Nurkiewicz
Jawaban David Wallace tentang validasi kerangka kerja menjawab pertanyaan saya sepenuhnya sehingga saya menerima yang satu itu, tetapi +1 untuk menunjukkan bahwa pelari ini tidak dapat digunakan dengan pelari lain, seperti pelari Musim Semi. Terima kasih!
OceanBlue
1
Saya menggunakan Spring Boot dan saya dapat mengatakan bahwa SpringJUnit4ClassRunnersecara otomatis menginisialisasi tiruan untuk saya. Aku tidak tahu tentang Spring yang biasa.
gustavohenke