Memulai dengan Mockito @Mock, @Spy, @Captor dan @InjectMocks

1. Ikhtisar

Dalam tutorial ini, kita akan membahas anotasi library Mockito - @Mock , @Spy , @Captor , dan @InjectMocks .

Untuk kebaikan Mockito lainnya, lihat serinya di sini.

2. Aktifkan Anotasi Mockito

Sebelum melangkah lebih jauh, mari jelajahi berbagai cara untuk mengaktifkan penggunaan anotasi dengan pengujian Mockito.

2.1. MockitoJUnitRunner

Opsi pertama yang kita miliki adalah membuat anotasi pengujian JUnit dengan MockitoJUnitRunner seperti pada contoh berikut:

@RunWith(MockitoJUnitRunner.class) public class MockitoAnnotationTest { ... }

2.2. MockitoAnnotations.initMocks ()

Sebagai alternatif, kita dapat mengaktifkan anotasi Mockito secara terprogram juga, dengan menjalankan MockitoAnnotations.initMocks () :

@Before public void init() { MockitoAnnotations.initMocks(this); }

2.3. MockitoJUnit.rule ()

Terakhir, kita bisa menggunakan MockitoJUnit.rule () seperti yang ditunjukkan di bawah ini:

public class MockitoInitWithMockitoJUnitRuleUnitTest { @Rule public MockitoRule initRule = MockitoJUnit.rule(); ... }

Dalam hal ini, kita harus ingat untuk membuat aturan kita menjadi publik .

3. Anotasi @Mock

Anotasi yang paling banyak digunakan di Mockito adalah @Mock . Kita dapat menggunakan @Mock untuk membuat dan memasukkan contoh tiruan tanpa harus memanggil Mockito.mock secara manual.

Dalam contoh berikut - kami akan membuat ArrayList tiruan dengan cara manual tanpa menggunakan anotasi @Mock :

@Test public void whenNotUseMockAnnotation_thenCorrect() { List mockList = Mockito.mock(ArrayList.class); mockList.add("one"); Mockito.verify(mockList).add("one"); assertEquals(0, mockList.size()); Mockito.when(mockList.size()).thenReturn(100); assertEquals(100, mockList.size()); }

Dan sekarang kami akan melakukan hal yang sama tetapi kami akan menyuntikkan tiruan menggunakan anotasi @Mock :

@Mock List mockedList; @Test public void whenUseMockAnnotation_thenMockIsInjected() { mockedList.add("one"); Mockito.verify(mockedList).add("one"); assertEquals(0, mockedList.size()); Mockito.when(mockedList.size()).thenReturn(100); assertEquals(100, mockedList.size()); }

Perhatikan bagaimana - dalam kedua contoh, kita berinteraksi dengan tiruan dan memverifikasi beberapa interaksi ini - hanya untuk memastikan bahwa tiruan tersebut berperilaku dengan benar.

4. Anotasi @Spy

Sekarang - mari kita lihat cara menggunakan anotasi @Spy untuk memata-matai instance yang ada.

Dalam contoh berikut - kami membuat mata-mata dari Daftar dengan cara lama tanpa menggunakan anotasi @Spy :

@Test public void whenNotUseSpyAnnotation_thenCorrect() { List spyList = Mockito.spy(new ArrayList()); spyList.add("one"); spyList.add("two"); Mockito.verify(spyList).add("one"); Mockito.verify(spyList).add("two"); assertEquals(2, spyList.size()); Mockito.doReturn(100).when(spyList).size(); assertEquals(100, spyList.size()); }

Sekarang mari kita lakukan hal yang sama - memata-matai daftar - tetapi lakukan dengan menggunakan anotasi @Spy :

@Spy List spiedList = new ArrayList(); @Test public void whenUseSpyAnnotation_thenSpyIsInjectedCorrectly() { spiedList.add("one"); spiedList.add("two"); Mockito.verify(spiedList).add("one"); Mockito.verify(spiedList).add("two"); assertEquals(2, spiedList.size()); Mockito.doReturn(100).when(spiedList).size(); assertEquals(100, spiedList.size()); }

Perhatikan bagaimana, seperti sebelumnya - kami berinteraksi dengan mata-mata di sini untuk memastikannya berperilaku dengan benar. Dalam contoh ini kami:

  • Digunakan nyata metode spiedList.add () untuk menambahkan elemen ke spiedList .
  • Stub metode spiedList.size () untuk mengembalikan 100, bukan 2 menggunakan Mockito.doReturn () .

5. Anotasi @Captor

Berikutnya - mari kita lihat cara menggunakan anotasi @Captor untuk membuat instance ArgumentCaptor .

Dalam contoh berikut - kami membuat ArgumentCaptor dengan cara lama tanpa menggunakan anotasi @Captor :

@Test public void whenNotUseCaptorAnnotation_thenCorrect() { List mockList = Mockito.mock(List.class); ArgumentCaptor arg = ArgumentCaptor.forClass(String.class); mockList.add("one"); Mockito.verify(mockList).add(arg.capture()); assertEquals("one", arg.getValue()); }

Sekarang mari kita gunakan @Captor untuk tujuan yang sama - untuk membuat instance ArgumentCaptor :

@Mock List mockedList; @Captor ArgumentCaptor argCaptor; @Test public void whenUseCaptorAnnotation_thenTheSam() { mockedList.add("one"); Mockito.verify(mockedList).add(argCaptor.capture()); assertEquals("one", argCaptor.getValue()); }

Perhatikan bagaimana pengujian menjadi lebih sederhana dan lebih mudah dibaca saat kita mengeluarkan logika konfigurasi.

6. Anotasi @Inject

Sekarang - mari kita bahas cara menggunakan anotasi @InjectMocks - untuk memasukkan bidang tiruan ke dalam objek yang diuji secara otomatis.

Dalam contoh berikut - kami menggunakan @InjectMocks untuk memasukkan mock wordMap ke dalam MyDictionary dic :

@Mock Map wordMap; @InjectMocks MyDictionary dic = new MyDictionary(); @Test public void whenUseInjectMocksAnnotation_thenCorrect() { Mockito.when(wordMap.get("aWord")).thenReturn("aMeaning"); assertEquals("aMeaning", dic.getMeaning("aWord")); }

Dan inilah kelas MyDictionary :

public class MyDictionary { Map wordMap; public MyDictionary() { wordMap = new HashMap(); } public void add(final String word, final String meaning) { wordMap.put(word, meaning); } public String getMeaning(final String word) { return wordMap.get(word); } } 

7. Menyuntikkan Mock ke Spy

Mirip dengan tes di atas, kami mungkin ingin menyuntikkan tiruan ke mata-mata:

@Mock Map wordMap; @Spy MyDictionary spyDic = new MyDictionary();

Namun, Mockito tidak mendukung penyuntikan tiruan ke mata-mata, dan tes berikut menghasilkan pengecualian:

@Test public void whenUseInjectMocksAnnotation_thenCorrect() { Mockito.when(wordMap.get("aWord")).thenReturn("aMeaning"); assertEquals("aMeaning", spyDic.getMeaning("aWord")); }

Jika kita ingin menggunakan tiruan dengan mata-mata, kita dapat menyuntikkan tiruan secara manual melalui konstruktor:

MyDictionary(Map wordMap) { this.wordMap = wordMap; }

Alih-alih menggunakan anotasi, sekarang kita dapat membuat mata-mata secara manual:

@Mock Map wordMap; MyDictionary spyDic; @Before public void init() { MockitoAnnotations.initMocks(this); spyDic = Mockito.spy(new MyDictionary(wordMap)); } 

Tes sekarang akan berlalu.

8. Mengalami NPE Saat Menggunakan Anotasi

Seringkali, kita mungkin mengalami NullPointerException saat kita mencoba untuk benar-benar menggunakan instance yang dianotasi dengan @Mock atau @Spy :

public class MockitoAnnotationsUninitializedUnitTest { @Mock List mockedList; @Test(expected = NullPointerException.class) public void whenMockitoAnnotationsUninitialized_thenNPEThrown() { Mockito.when(mockedList.size()).thenReturn(1); } }

Sering kali, ini terjadi hanya karena kami lupa mengaktifkan anotasi Mockito dengan benar.

Jadi, kita harus ingat bahwa setiap kali kita ingin menggunakan anotasi Mockito, kita harus mengambil langkah ekstra dan memulainya seperti yang sudah kita jelaskan sebelumnya.

9. Catatan

Terakhir - berikut beberapa catatan tentang anotasi Mockito:

  • Anotasi Mockito meminimalkan kode pembuatan tiruan yang berulang
  • Mereka membuat tes lebih mudah dibaca
  • @InjectMocks diperlukan untuk menyuntikkan baik @Spy dan @Mock contoh

10. Kesimpulan

Dalam tutorial singkat ini, kami menunjukkan dasar-dasar anotasi di perpustakaan Mockito .

Penerapan semua contoh ini dapat ditemukan di GitHub. Ini adalah proyek Maven, jadi semestinya mudah untuk mengimpor dan menjalankannya apa adanya.

Dan tentu saja, untuk kebaikan Mockito lainnya, lihat serinya di sini.