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

1. Gambaran keseluruhan

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

Untuk kebaikan Mockito lebih banyak lagi, lihat siri ini di sini.

2. Dayakan Anotasi Mockito

Sebelum melangkah lebih jauh, mari kita meneroka pelbagai cara untuk membolehkan penggunaan anotasi dengan ujian Mockito.

2.1. MockitoJUnitRunner

Pilihan pertama yang kita ada adalah memberi anotasi ujian JUnit dengan MockitoJUnitRunner seperti contoh berikut:

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

2.2. MockitoAnnotations.initMocks ()

Sebagai alternatif, kami boleh mengaktifkan anotasi Mockito secara terprogram juga, dengan menggunakan MockitoAnnotations.initMocks () :

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

2.3. Peraturan MockitoJUnit ()

Terakhir, kita dapat menggunakan MockitoJUnit.rule () seperti gambar di bawah:

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

Dalam kes ini, kita mesti ingat untuk membuat peraturan kita terbuka .

3. @ Anotasi Mock

Anotasi yang paling banyak digunakan di Mockito ialah @Mock . Kita boleh menggunakan @Mock untuk membuat dan menyuntik contoh yang diejek tanpa perlu memanggil Mockito.mock secara manual.

Dalam contoh berikut - kami akan membuat ArrayList yang diejek 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 kita akan melakukan perkara yang sama tetapi kita akan menyuntik 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-dua contoh tersebut, kita berinteraksi dengan ejekan dan mengesahkan beberapa interaksi ini - hanya untuk memastikan bahawa ejekan itu berlaku dengan betul.

4. Anotasi @Spy

Sekarang - mari lihat bagaimana menggunakan anotasi @Spy untuk mengintip kejadian yang ada.

Dalam contoh berikut - kami membuat mata-mata 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 melakukan perkara yang sama - mengintip senarai - tetapi melakukannya menggunakan penjelasan @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 pengintip di sini untuk memastikan bahawa ia berkelakuan dengan betul. Dalam contoh ini kita:

  • Menggunakan kaedah sebenar spiedList.add () untuk menambahkan elemen ke dalam spiedList .
  • Menyekat kaedah spiedList.size () untuk mengembalikan 100 dan bukannya 2 menggunakan Mockito.doReturn () .

5. @Cotor Anotasi

Seterusnya - mari lihat bagaimana menggunakan anotasi @Captor untuk membuat contoh 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 contoh 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 ujian menjadi lebih mudah dan mudah dibaca ketika kita mengambil logik konfigurasi.

6. Anotasi @InjectMocks

Sekarang - mari kita bincangkan cara menggunakan anotasi @InjectMocks - untuk memasukkan medan tiruan ke objek yang diuji secara automatik.

Dalam contoh berikut - kami menggunakan @InjectMocks untuk menyuntikkan peta kata tiruan 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. Menyuntik ejekan ke mata-mata

Sama seperti ujian di atas, kami mungkin ingin menyuntik tiruan kepada pengintip:

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

Walau bagaimanapun, Mockito tidak menyokong menyuntik ejekan ke mata-mata, dan ujian berikut menghasilkan pengecualian:

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

Sekiranya kita ingin menggunakan tiruan dengan pengintip, kita dapat menyuntik tiruan secara manual melalui konstruktor:

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

Daripada menggunakan anotasi, kita sekarang boleh membuat pengintip secara manual:

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

Ujian sekarang akan lulus.

8. Menjalankan NPE Semasa Menggunakan Anotasi

Selalunya, kita mungkin mengalami NullPointerException apabila kita benar-benar menggunakan contoh yang diberi penjelasan dengan @Mock atau @Spy :

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

Selalunya, ini berlaku hanya kerana kita terlupa mengaktifkan anotasi Mockito dengan betul.

Oleh itu, kita harus ingat bahawa setiap kali kita mahu menggunakan anotasi Mockito, kita mesti mengambil langkah tambahan dan memulakannya seperti yang telah kita jelaskan sebelumnya.

9. Catatan

Akhirnya - berikut adalah beberapa nota mengenai anotasi Mockito:

  • Anotasi Mockito meminimumkan kod pembuatan tiruan berulang
  • Mereka menjadikan ujian lebih mudah dibaca
  • @InjectMocks adalah perlu untuk menyuntik kedua-dua @Spy dan @Mock keadaan

10. Kesimpulannya

Dalam tutorial ringkas ini, kami menunjukkan asas-asas anotasi di perpustakaan Mockito .

Pelaksanaan semua contoh ini boleh didapati di GitHub. Ini adalah projek Maven, jadi mudah untuk diimport dan dijalankan sebagaimana adanya.

Dan tentu saja, untuk lebih banyak kebaikan Mockito, lihat siri ini di sini.