Cara menggunakan Mockito dengan JUnit5

107

Bagaimana cara menggunakan injeksi dengan Mockito dan JUnit 5?

Di JUnit4 saya bisa menggunakan @RunWith(MockitoJUnitRunner.class)Annotation. Di JUnit5 tidak ada @RunWithAnotasi?

Daniel Käfer
sumber

Jawaban:

151

Ada berbagai cara untuk menggunakan Mockito - Saya akan membahasnya satu per satu.

Secara manual

Membuat tiruan secara manual dengan Mockito::mockkarya apa pun versi JUnitnya (atau uji framework dalam hal ini).

Berbasis Anotasi

Menggunakan @Mock -annotation dan panggilan terkait MockitoAnnotations::initMocks untuk membuat tiruan berfungsi terlepas dari versi JUnit (atau kerangka kerja pengujian dalam hal ini, tetapi Java 9 dapat ikut campur di sini, bergantung pada apakah kode pengujian berakhir di modul atau tidak).

Ekstensi Mockito

JUnit 5 memiliki model ekstensi yang kuat dan Mockito baru-baru ini menerbitkannya di bawah ID grup / artefak org.mockito : mockito-junit-jupiter .

Anda dapat menerapkan ekstensi dengan menambahkan @ExtendWith(MockitoExtension.class)ke kelas pengujian dan membuat anotasi bidang tiruan dengan @Mock. Dari MockitoExtensionJavaDoc:

@ExtendWith(MockitoExtension.class)
public class ExampleTest {

    @Mock
    private List list;

    @Test
    public void shouldDoSomething() {
        list.add(100);
    }

}

Dokumentasi MockitoExtension menjelaskan cara lain untuk membuat instance tiruan, misalnya dengan injeksi konstruktor (jika Anda mereferensikan kolom final di kelas pengujian).

Tanpa Aturan, Tanpa Pelari

Aturan JUnit 4 dan pelari tidak berfungsi di JUnit 5, jadi pelariMockitoRule dan pelari Mockito tidak dapat digunakan.

Nicolai Parlog
sumber
6
Sekarang ada Ekstensi Mockito Junit5 resmi yang setara dengan MockitoJUnitRunner -> mockito-junit-jupiter
dan carter
Ketika ekstensi resmi untuk Mockito dirilis, tulis posting blog dengan detail lebih lanjut tentang cara mengkonfigurasi dan menggunakannya: solidsoft.wordpress.com/2018/03/27/…
Marcin Zajączkowski
Apakah metode yang dianotasi @Testperlu menjadi publik atau "paket pribadi" sudah cukup baik?
Geek
Saat menjalankan pengujian dengan Jupiter (sering disebut sebagai "JUnit 5"), metode pengujian hanya perlu terlihat paket.
Nicolai Parlog
60

Gunakan Mockito's MockitoExtension. Ekstensi terdapat dalam artefak baru mockito-junit-jupiter:

<dependency>
    <groupId>org.mockito</groupId>
    <artifactId>mockito-junit-jupiter</artifactId>
    <version>2.23.4</version>
    <scope>test</scope>
</dependency>

Ini memungkinkan Anda untuk menulis tes seperti yang Anda lakukan dengan JUnit 4:

import org.mockito.junit.jupiter.MockitoExtension;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;

@ExtendWith(MockitoExtension.class)
class MyTest {

    @Mock
    private Foo foo;

    @InjectMocks
    private Bar bar; // constructor injection

    ...
}
Jonathan
sumber
7
@ExtendWith(MockitoExtension.class)setara @RunWith(MockitoJUnitRunner.class)dengan JUnit4
Sergey Nemchinov
Dapatkah saya melakukan beberapa panggilan metode dengan nilai pengembalian yang berbeda pada metode objek Mock menggunakan MockitoExtension.class di JUnit5
Raj Hassani
@RajHassani Ya Anda bisa, lihat di sini .
Jonathan
10

Ada berbagai cara untuk dilakukan, tetapi cara yang lebih bersih dan yang juga menghormati filosofi JUnit 5 adalah membuat org.junit.jupiter.api.extension.Extensionuntuk Mockito.

1) Membuat tiruan secara manual menghilangkan manfaat pemeriksaan Mockito tambahan untuk memastikan Anda menggunakan kerangka kerja dengan benar.

2) Memanggil MockitoAnnotations.initMocks(this)di setiap kelas pengujian adalah kode pelat boiler yang dapat kita hindari.
Dan membuat penyiapan ini di kelas abstrak juga bukan solusi yang baik.
Ini memasangkan setiap kelas tes ke kelas dasar.
Jika kemudian Anda memerlukan kelas pengujian dasar baru untuk alasan yang baik, Anda menyelesaikannya dengan hierarki kelas 3 tingkat. Harap hindari itu.

3) Aturan Uji adalah kekhususan JUnit 4.
Jangan pernah memikirkan itu.
Dan dokumentasinya jelas tentang itu:

Namun, jika Anda bermaksud mengembangkan ekstensi baru untuk JUnit 5, gunakan model ekstensi baru JUnit Jupiter alih-alih model berbasis aturan JUnit 4.

4) Test Runner sebenarnya bukan cara untuk memperluas kerangka JUnit 5.
JUnit 5 menyederhanakan Runners of JUnit 4 dengan menyediakan model ekstensi untuk menulis tes berkat JUnit 5 Extensions.
Jangan pernah memikirkan itu.

Jadi nikmatilah org.junit.jupiter.api.extension.Extensioncaranya.


EDIT: Sebenarnya, Mockito membundel ekstensi jupiter: mockito-junit-jupiter

Kemudian, sangat mudah digunakan:

import org.mockito.junit.jupiter.MockitoExtension;

@ExtendWith(MockitoExtension.class)
public class FooTest {
     ...    
}

Ini adalah tambahan dari jawaban luar biasa dari Jonathan.

Dengan menambahkan mockito-junit-jupiterartefak sebagai ketergantungan , penggunaan @ExtendWith(MockitoExtension.class)menghasilkan pengecualian berikut saat pengujian dijalankan:

java.lang.NoSuchMethodError: org.junit.platform.commons.support.AnnotationSupport.findAnnotation (Ljava / util / Opsional; Ljava / lang / Class;) Ljava / util / Opsional;

Masalahnya adalah itu mockito-junit-jupitertergantung pada dua perpustakaan independen. Misalnya untuk mockito-junit-jupiter:2.19.0:

<dependency>
  <groupId>org.mockito</groupId>
  <artifactId>mockito-core</artifactId>
  <version>2.19.0</version>
  <scope>compile</scope>
</dependency>
<dependency>
  <groupId>org.junit.jupiter</groupId>
  <artifactId>junit-jupiter-api</artifactId>
  <version>5.1.0</version>
  <scope>runtime</scope>
</dependency>

Masalahnya adalah saya sudah terbiasa junit-jupiter-api:5.0.1.

Sehingga junit-jupiter-apibergerak masih sering dalam hal API, pastikan Anda tergantung pada versi yang sama dari junit-jupiter-apiyang mockito-junit-jupitertergantung pada.

davidxxx
sumber
mengapa tidak mockito-junit-jupitermenarik versi yang tepat junit-jupiter-api?
haelix
@haelix Karena strategi versi yang digunakan untuk ketergantungan ini bergantung pada pustaka Mockito. Lihat versinya di sini mockito-junit-jupiter:2.19.0. Sedangkan versi JUnit Jupiter dimulai dengan 5. mockito-junit-jupiter harus menentukan dalam artefak pengenalnya dua hal (versi Mockito dan versi JUnit Jupiter) untuk memperjelas. Misalnya mockito-junit-jupiter-5.1:2.19.0untuk menyampaikan bahwa perpustakaan dirancang untuk JUnit Jupiter 5.1.
davidxxx
MockitoExtensiontampaknya tidak ada di mockito-coreversi 3.0.0.
Thunderforge
1
@Thunderforge Ini didefinisikan dimockito-junit-jupiter
davidxxx
3

Anda harus menggunakan @ExtendWithanotasi baru .

Sayangnya belum ada ekstensi yang dirilis. Di github, Anda dapat melihat implementasi beta untuk ekstensi tersebut. sebagai contoh uji demo .

Daniel Käfer
sumber