Mockito - perbedaan antara doReturn () dan when ()

196

Saat ini saya sedang dalam proses menggunakan Mockito untuk mengolok-olok objek lapisan layanan saya dalam aplikasi Spring MVC di mana saya ingin menguji metode Pengontrol saya. Namun, karena saya telah membaca tentang spesifikasi Mockito, saya telah menemukan bahwa metode doReturn(...).when(...)ini setara dengan when(...).thenReturn(...). Jadi, pertanyaan saya adalah apa gunanya memiliki dua metode yang melakukan hal yang sama atau apa perbedaan halus antara doReturn(...).when(...)dan when(...).thenReturn(...)?

Bantuan apa pun akan dihargai.

Macan kumbang
sumber
1
Javadoc memiliki beberapa kasus doReturn()yang bermanfaat.
Sotirios Delimanolis
5
Saya pikir salah satu perbedaan utama adalah doReturn (...). When (..) adalah yang lebih tua dan jenisnya tidak aman dan karenanya kita dapat menggunakannya kadang-kadang ketika kompiler terus mengeluh tentang casting. When (..). ThenReturn (..) jauh lebih baik dalam hal jenis keamanan
user2511882

Jawaban:

227

Dua sintaks untuk stubbing kira-kira sama. Namun, Anda selalu dapat menggunakan doReturn/whenuntuk stubbing; tetapi ada kasus di mana Anda tidak bisa menggunakan when/thenReturn. Metode stubbing void adalah salah satunya. Lainnya termasuk digunakan dengan mata-mata Mockito, dan mematikan metode yang sama lebih dari sekali.

Satu hal yang when/thenReturnmemberi Anda, itudoReturn/when tidak, adalah memeriksa jenis nilai yang Anda kembalikan, pada waktu kompilasi. Namun, saya percaya ini hampir tidak ada nilainya - jika Anda salah mengetik, Anda akan segera tahu setelah menjalankan tes.

Saya sangat merekomendasikan hanya menggunakan doReturn/when. Tidak ada gunanya mempelajari dua sintaks ketika satu akan dilakukan.

Anda mungkin ingin merujuk ke jawaban saya di "tata bahasa" Pembentukan Mockito - jawaban yang lebih rinci untuk pertanyaan yang sangat terkait.

Dawood ibn Kareem
sumber
16
Saya agak tidak setuju dengan David. Saya sering mengalami situasi di mana saya mengembalikan jenis yang salah ketika menggunakan doReturn/whendan menghabiskan beberapa menit berikutnya mencari tahu apa yang salah. Pengecekan tipe tipe kompilasi menjadi sangat berguna when/thenReturn.
Saket
11
Ingatlah bahwa Mockito menyarankan Anda menggunakan yang digunakan when/thenReturnalih-alih doReturn/when.
CodyEngel
2
@CodyEngel dan tidak ada alasan untuk rekomendasi seperti itu, selain dari apa yang telah saya uraikan dalam jawaban saya di sini dan di stackoverflow.com/q/11462697 . Beberapa tahun yang lalu, saya membahas hal ini dengan Brice Dutheil, yang saat ini bertindak sebagai pengembang utama Mockito, dan untuk yang terbaik dari ingatan saya, dia setuju. Saya akan memintanya untuk mengirim komentar di sini (tidak ada jaminan bahwa dia akan melakukannya).
Dawood ibn Kareem
18
The javadoc menyatakan bahwa doReturn/whenadalah trade-off. Tim tidak merekomendasikan satu atau lain cara tetapi perhatikan when/thenpendekatannya lebih intuitif, lebih mudah dibaca dan menawarkan kompilasi waktu pemeriksaan, itu adalah pendekatan yang membuat Mockito populer dan mudah digunakan, jangan lupa bahwa ketika basis kode dibagi oleh berbagai keahlian dalam tim Anda; namun memiliki kelemahan terkait mata-mata dan metode batal.
Brice
5
Sekadar catatan: doReturn()memiliki kelemahan besar untuk beralih ke pengkodean gaya panggilan metode YODA. Masalahnya kemudian ditulis terlebih dahulu yaitu. Kebanyakan orang membaca dari kiri ke kanan; jadi Anda sekarang harus selalu ingat untuk membalikkan logika return-when di kepala Anda.
GhostCat
199

Kedua pendekatan berperilaku berbeda jika Anda menggunakan objek mata-mata (beranotasi dengan @Spy) daripada tiruan (beranotasi dengan @Mock):

  • when(...) thenReturn(...) membuat panggilan metode nyata tepat sebelum nilai yang ditentukan akan dikembalikan. Jadi jika metode yang dipanggil melempar Exception Anda harus menghadapinya / mengejeknya dll. Tentu saja Anda masih mendapatkan hasil Anda (apa yang Anda definisikan thenReturn(...))

  • doReturn(...) when(...) tidak memanggil metode sama sekali .

Contoh:

public class MyClass {
     protected String methodToBeTested() {
           return anotherMethodInClass();
     }

     protected String anotherMethodInClass() {
          throw new NullPointerException();
     }
}

Uji:

@Spy
private MyClass myClass;

// ...

// would work fine
doReturn("test").when(myClass).anotherMethodInClass();

// would throw a NullPointerException
when(myClass.anotherMethodInClass()).thenReturn("test");
akcasoy
sumber
37
Perilaku ini hanya berfungsi untuk objek mata-mata, karena merupakan "pembungkus" objek nyata. Dalam kasus objek yang diejek, tidak masalah apakah itu ketika / thenReturn atau doReturn / kapan. Objek yang diolok-olok tidak pernah menyebut metode nyata.
Rafael Orágio
Bisakah Anda memberikan informasi lebih lanjut mengapa kita perlu menggunakan fungsi ini? Saya tidak melihat kasus penggunaan praktis. Maksud pengujian adalah mengkonfirmasi kebenaran kode dalam berbagai kasus penggunaan. Jika calll metode melempar tes pengecualian harus melempar pengecualian, tidak mengembalikan nilai
Gleichmut
@ Gleichmut Ini adalah skenario hipotetis, di mana saya menunjukkan penggunaan / keunggulan doReturn. Dalam aplikasi nyata, sebuah metode yang hanya mengembalikan pengecualian tentu saja tidak masuk akal .. tetapi Anda memiliki metode (mungkin tidak begitu tipis seperti ini) yang dapat melempar pengecualian dalam kondisi tertentu ..
akcasoy
1
Hanya untuk klarifikasi: Metode when (). ThenReturn () - memanggil metode aktual (mata-mata - tidak masalah untuk mengejek) hanya sekali. Ini terjadi pada baris yang Anda tentukan perilaku tiruan (ketika ( myClass.anotherMethodInClass () .thenRet ...). Setelah itu metode yang sebenarnya tidak pernah dipanggil lagi. Mungkin baik untuk mengetahui apakah Anda mengharapkan logika dekorator saat membaca penjelasan. di atas
Jonas
Ini sepertinya bukan keuntungan dari doReturn(), itu tampak seperti penyalahgunaan perpustakaan. Tujuan memata-matai bukannya mengejek murni adalah untuk mengambil keuntungan dari panggilan nyata. Mereka juga memperingatkan agar tidak menggunakan Spies seperti ini: github.com/mockito/mockito/wiki/Using-Spies-(and-Fakes) (dan merekomendasikan untuk memperluas kelas dan mengganti metode sebagai gantinya)
Matthew Read
13

Javadoc Mockito tampaknya memberi tahu mengapa menggunakan doReturn()alih-alih when() Gunakan doReturn () pada kesempatan langka saat Anda tidak dapat menggunakan Mockito.when (Objek).

Berhati-hatilah bahwa Mockito.when (Object) selalu disarankan untuk stubbing karena argumennya aman dan lebih mudah dibaca (terutama ketika stubbing panggilan berurutan).

Inilah saat-saat langka ketika doReturn () berguna:

1. Saat memata-matai benda nyata dan memanggil metode nyata pada mata-mata membawa efek samping

List list = new LinkedList(); List spy = spy(list);

// Impossible: metode nyata disebut so spy.get (0) melempar IndexOutOfBoundsException (daftarnya belum kosong)

when(spy.get(0)).thenReturn("foo");

// Anda harus menggunakan doReturn () untuk mematikan: doReturn("foo").when(spy).get(0);

2. Mengesampingkan pengecualian-stubbing sebelumnya:

when(mock.foo()).thenThrow(new RuntimeException());

// Impossible: metode foo () exception-stubbed dipanggil jadi RuntimeException dilempar. when(mock.foo()).thenReturn("bar");

// Anda harus menggunakan doReturn () untuk mematikan:

doReturn("bar").when(mock).foo(); Skenario di atas menunjukkan kompromi sintaksis elegan Mockito. Perhatikan bahwa skenarionya sangat langka. Memata-matai harus sporadis dan mengabaikan pengecualian-sangat jarang. Belum lagi bahwa secara umum mengesampingkan stubbing adalah bau kode potensial yang menunjukkan terlalu banyak stubbing.


sumber
6

Melanjutkan jawaban ini , Ada perbedaan lain bahwa jika Anda ingin metode Anda mengembalikan nilai yang berbeda misalnya saat pertama kali dipanggil, kedua kalinya dipanggil dll maka Anda dapat memberikan nilai jadi misalnya ...

PowerMockito.doReturn(false, false, true).when(SomeClass.class, "SomeMethod", Matchers.any(SomeClass.class));

Jadi itu akan mengembalikan false ketika metode ini dipanggil dalam test case yang sama dan kemudian itu akan kembali false lagi dan yang terakhir benar.

AZ_
sumber