Menggunakan Mockito ArgumentCaptor

1. Gambaran keseluruhan

Dalam tutorial ini, kita akan membahas kes penggunaan biasa menggunakan Mockito ArgumentCaptor dalam ujian unit kami.

Sebagai alternatif, untuk kes penggunaan Mockito.verify yang lain , lihat Buku Memeriksa Mockito kami.

2. Menggunakan ArgumentCaptor

ArgumentCaptor membolehkan kita menangkap argumen yang diserahkan kepada kaedah untuk memeriksanya. Ini sangat berguna apabila kita tidak dapat mengakses argumen di luar kaedah yang ingin kita uji.

Sebagai contoh, pertimbangkan kelas Perkhidmatan Email dengan kaedah hantar yang ingin kami uji:

public class EmailService { private DeliveryPlatform platform; public EmailService(DeliveryPlatform platform) { this.platform = platform; } public void send(String to, String subject, String body, boolean html) { Format format = Format.TEXT_ONLY; if (html) { format = Format.HTML; } Email email = new Email(to, subject, body); email.setFormat(format); platform.deliver(email); } ... }

Dalam Perkhidmatan E-mel . hantar , perhatikan bagaimana platform.deliver mengambil E - mel baru sebagai hujah. Sebagai sebahagian daripada ujian kami, kami ingin memastikan bahawa bidang format E - mel baru ditetapkan ke Format.HTML . Untuk melakukan ini, kita perlu menangkap dan memeriksa argumen yang disampaikan ke platform.deliver .

Mari lihat bagaimana kita boleh menggunakan ArgumentCaptor untuk menolong kita.

2.1. Sediakan Ujian Unit

Pertama, mari buat kelas ujian unit kami:

@RunWith(MockitoJUnitRunner.class) public class EmailServiceUnitTest { @Mock DeliveryPlatform platform; @InjectMocks EmailService emailService; ... }

Kami menggunakan anotasi @Mock untuk mengejek DeliveryPlatform , yang secara automatik disuntik ke dalam Perkhidmatan E - mel kami dengan anotasi @InjectMocks . Rujuk artikel Anotasi Mockito kami untuk keterangan lebih lanjut.

2.2. Tambah Medan ArgumentCaptor

Kedua, mari tambahkan medan ArgumentCaptor jenis E-mel baru untuk menyimpan argumen kami yang ditangkap:

@Captor ArgumentCaptor emailCaptor;

2.3. Tangkap Hujah

Ketiga, mari kita gunakan Mockito.verify dengan ArgumentCaptor untuk menangkap E - mel :

Mockito.verify(platform).deliver(emailCaptor.capture());

Kami kemudian dapat memperoleh nilai yang diambil dan menyimpannya sebagai objek E - mel baru :

Email emailCaptorValue = emailCaptor.getValue();

2.4. Periksa Nilai yang Ditangkap

Akhirnya, mari kita lihat keseluruhan ujian dengan penegasan untuk memeriksa objek E-mel yang ditangkap :

@Test public void whenDoesSupportHtml_expectHTMLEmailFormat() { String to = "[email protected]"; String subject = "Using ArgumentCaptor"; String body = "Hey, let'use ArgumentCaptor"; emailService.send(to, subject, body, true); Mockito.verify(platform).deliver(emailCaptor.capture()); Email value = emailCaptor.getValue(); assertEquals(Format.HTML, value.getFormat()); }

3. Mengelakkan Stubbing

Walaupun kita dapat menggunakan ArgumentCaptor dengan stubbing , kita biasanya harus mengelakkannya. Untuk menjelaskan, dalam Mockito, ini secara umum bermaksud mengelakkan penggunaan ArgumentCaptor dengan Mockito . Ketika . Dengan stubbing, kita harus menggunakan ArgumentMatcher sebagai gantinya.

Mari kita perhatikan beberapa sebab mengapa kita harus mengelakkan diri daripada menusuk.

3.1. Kemerosotan Ujian Berkurang

Pertama, pertimbangkan ujian mudah :

Credentials credentials = new Credentials("baeldung", "correct_password", "correct_key"); Mockito.when(platform.authenticate(Mockito.eq(credentials))) .thenReturn(AuthenticationStatus.AUTHENTICATED); assertTrue(emailService.authenticatedSuccessfully(credentials));

Di sini, kami menggunakan Mockito.eq (kelayakan) untuk menentukan kapan tiruan harus mengembalikan objek.

Seterusnya, pertimbangkan ujian yang sama menggunakan ArgumentCaptor sebagai gantinya:

Credentials credentials = new Credentials("baeldung", "correct_password", "correct_key"); Mockito.when(platform.authenticate(credentialsCaptor.capture())) .thenReturn(AuthenticationStatus.AUTHENTICATED); assertTrue(emailService.authenticatedSuccessfully(credentials)); assertEquals(credentials, credentialsCaptor.getValue());

Berbeza dengan ujian pertama, perhatikan bagaimana kita harus melakukan penegasan tambahan pada baris terakhir untuk melakukan hal yang sama seperti Mockito.eq (tauliah) .

Akhirnya, perhatikan bagaimana ia tidak jelas dengan jelas apa yang dirujuk oleh credentialsCaptor.capture () . Ini kerana kita harus membuat penangkap di luar garis yang kita gunakan, yang mengurangkan kebolehbacaan.

3.2. Penyetempatan Kecacatan Berkurang

Sebab lain ialah jika emailService.authenticatedSuccessently tidak memanggil platform.authenticate , kami akan mendapat pengecualian:

org.mockito.exceptions.base.MockitoException: No argument value was captured!

Ini kerana kaedah kami yang ditikam belum mendapat argumen. Walau bagaimanapun, masalah sebenarnya bukan dalam ujian kita sendiri, tetapi kaedah sebenar yang sedang kita uji.

Dengan kata lain, ini salah mengarahkan kita kepada pengecualian dalam ujian, sedangkan kecacatan sebenarnya adalah dalam kaedah yang kita uji.

4. Kesimpulan

Dalam tutorial ringkas ini, kami melihat kes penggunaan umum menggunakan ArgumentCaptor . Kami juga melihat sebab-sebab untuk mengelakkan penggunaan ArgumentCaptor dengan stubbing. Seperti biasa, semua contoh kod kami boleh didapati di GitHub.