Bagaimana cara menggunakan injeksi dengan Mockito dan JUnit 5?
Di JUnit4 saya bisa menggunakan @RunWith(MockitoJUnitRunner.class)
Annotation. Di JUnit5 tidak ada @RunWith
Anotasi?
Bagaimana cara menggunakan injeksi dengan Mockito dan JUnit 5?
Di JUnit4 saya bisa menggunakan @RunWith(MockitoJUnitRunner.class)
Annotation. Di JUnit5 tidak ada @RunWith
Anotasi?
Jawaban:
Ada berbagai cara untuk menggunakan Mockito - Saya akan membahasnya satu per satu.
Membuat tiruan secara manual dengan Mockito::mock
karya apa pun versi JUnitnya (atau uji framework dalam hal ini).
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).
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 MockitoExtension
JavaDoc:
@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).
Aturan JUnit 4 dan pelari tidak berfungsi di JUnit 5, jadi pelariMockitoRule
dan pelari Mockito tidak dapat digunakan.
@Test
perlu menjadi publik atau "paket pribadi" sudah cukup baik?
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
...
}
@ExtendWith(MockitoExtension.class)
setara @RunWith(MockitoJUnitRunner.class)
dengan JUnit4
Ada berbagai cara untuk dilakukan, tetapi cara yang lebih bersih dan yang juga menghormati filosofi JUnit 5 adalah membuat org.junit.jupiter.api.extension.Extension
untuk 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.Extension
caranya.
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-jupiter
artefak 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-jupiter
tergantung 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-api
bergerak masih sering dalam hal API, pastikan Anda tergantung pada versi yang sama dari junit-jupiter-api
yang mockito-junit-jupiter
tergantung pada.
mockito-junit-jupiter
menarik versi yang tepat junit-jupiter-api
?
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.0
untuk menyampaikan bahwa perpustakaan dirancang untuk JUnit Jupiter 5.1.
MockitoExtension
tampaknya tidak ada di mockito-core
versi 3.0.0.
mockito-junit-jupiter