Bagaimana cara menggunakan ArgumentCaptor untuk stubbing?

161

Dalam dokumentasi dan javadocs Mockito dikatakan

Dianjurkan untuk menggunakan ArgumentCaptor dengan verifikasi tetapi tidak dengan stubbing.

tapi saya tidak mengerti bagaimana ArgumentCaptor dapat digunakan untuk stubbing. Dapatkah seseorang menjelaskan pernyataan di atas dan menunjukkan bagaimana ArgumentCaptor dapat digunakan untuk mematikan tulisan atau memberikan tautan yang menunjukkan bagaimana hal itu dapat dilakukan?

Tidak tahu
sumber
1
Penjelasan super singkat & menyenangkan di sini: dzone.com/articles/…
Benj

Jawaban:

271

Dengan asumsi metode berikut untuk menguji:

public boolean doSomething(SomeClass arg);

Dokumentasi Mockito mengatakan bahwa Anda tidak boleh menggunakan penculik dengan cara ini:

when(someObject.doSomething(argumentCaptor.capture())).thenReturn(true);
assertThat(argumentCaptor.getValue(), equalTo(expected));

Karena Anda bisa menggunakan korek api saat mematikan:

when(someObject.doSomething(eq(expected))).thenReturn(true);

Tetapi verifikasi adalah cerita yang berbeda. Jika pengujian Anda perlu memastikan bahwa metode ini dipanggil dengan argumen khusus, gunakan ArgumentCaptordan inilah kasus yang dirancangnya:

ArgumentCaptor<SomeClass> argumentCaptor = ArgumentCaptor.forClass(SomeClass.class);
verify(someObject).doSomething(argumentCaptor.capture());
assertThat(argumentCaptor.getValue(), equalTo(expected));
Rorick
sumber
Terima kasih atas jawabannya. Saya punya pertanyaan. Pada blok kode ketiga kita tahu bahwa true dikembalikan hanya ketika diharapkan diteruskan ke doSomething. Tetapi kapan benar dikembalikan dalam blok kode kedua? Atau apakah someObject selalu mengembalikan true untuk beberapa Metode dalam kasus itu?
Can't Tell
Hm, saya yakin maksud Anda "Tapi kapan benar dikembalikan dalam blok kode ketiga ?". Pada blok kode ketiga kami hanya tidak peduli untuk nilai kembali dan membiarkannya menjadi default. Untuk boolean false, bukan true.
Rorick
Tidak, saya menghitung semua blok latar belakang abu-abu sebagai blok kode. Termasuk liner pertama. Saya merujuk ke baris ketika (someObject.doSomething (argumentCaptor.capture ())). ThenReturn (true);
Tidak Dapat Memberitahu
Ah maaf. Ya, dalam hal ini benar akan selalu dikembalikan.
Rorick
3
tidak yakin alasan untuk "tidak digunakan dengan stubbing" adalah alasan sederhana. korek api tidak memberi kami argumen yang diharapkan sebenarnya (hanya tipe) dan mengarah pada apa-apa dengan lulus ujian meskipun ada argumen yang mungkin salah.
dtc
0

Garis

when(someObject.doSomething(argumentCaptor.capture())).thenReturn(true);

akan melakukan hal yang sama seperti

when(someObject.doSomething(Matchers.any())).thenReturn(true);

Jadi, menggunakan argumentCaptor.capture () ketika stubbing tidak memiliki nilai tambah. Menggunakan Matchers.any () menunjukkan lebih baik apa yang sebenarnya terjadi dan karenanya lebih baik untuk dibaca. Dengan argumentCaptor.capture (), Anda tidak dapat membaca argumen apa yang benar-benar cocok. Dan alih-alih menggunakan sembarang (), Anda dapat menggunakan pencocokan yang lebih spesifik ketika Anda memiliki lebih banyak informasi (kelas dari argumen yang diharapkan), untuk meningkatkan pengujian Anda.

Dan masalah lain: Jika menggunakan argumentCaptor.capture () saat mematikan itu menjadi tidak jelas berapa banyak nilai yang Anda harapkan akan ditangkap setelah verifikasi. Kami ingin mengambil nilai selama verifikasi, bukan saat mematikan karena pada saat itu belum ada nilai untuk ditangkap. Jadi, apa yang ditangkap oleh metode yang ditangkap oleh para penculik selama stubbing? atau tidakkah ia menangkap sesuatu? Saya tidak punya jawaban untuk pertanyaan ini. Saya menganggapnya sebagai perilaku yang tidak terdefinisi dan saya tidak ingin menggunakan perilaku yang tidak terdefinisi.

Stefan Mondelaers
sumber
0

Hipotetis, jika pencarian mendarat Anda pada pertanyaan ini maka Anda mungkin menginginkan ini:

doReturn(someReturn).when(someObject).doSomething(argThat(argument -> argument.getName().equals("Bob")));

Mengapa? Karena seperti saya, Anda menghargai waktu dan Anda tidak akan mengimplementasikannya.equals hanya demi skenario uji tunggal.

Dan 99% tes berantakan dengan null dikembalikan dari Mock dan dalam desain yang masuk akal Anda akan menghindari pengembalian nulldi semua biaya, menggunakan Optionalatau pindah ke Kotlin. Ini menyiratkan bahwa verifytidak perlu sering digunakan dan ArgumentCaptors terlalu membosankan untuk ditulis.

Terong
sumber