Simulasikan panggilan pertama gagal, panggilan kedua berhasil


119

Saya ingin menggunakan Mockito untuk menguji kode (yang disederhanakan) di bawah ini. Saya tidak tahu bagaimana memberi tahu Mockito untuk gagal pertama kali, lalu berhasil untuk kedua kalinya.

for(int i = 1; i < 3; i++) {
  String ret = myMock.doTheCall();

  if("Success".equals(ret)) {
    log.write("success");
  } else if ( i < 3 ) {
    log.write("failed, but I'll try again. attempt: " + i);
  } else {
    throw new FailedThreeTimesException();
  }
}

Saya dapat menyiapkan tes sukses dengan:

Mockito.when(myMock).doTheCall().thenReturn("Success");

Dan uji kegagalan dengan:

Mockito.when(myMock).doTheCall().thenReturn("you failed");

Tapi bagaimana saya bisa menguji bahwa jika gagal sekali (atau dua kali) lalu berhasil, tidak masalah?

Jawaban:


250

Dari dokumen :

Kadang-kadang kita perlu stub dengan nilai pengembalian / pengecualian yang berbeda untuk pemanggilan metode yang sama. Kasus penggunaan tipikal bisa jadi memperolok iterator. Versi asli Mockito tidak memiliki fitur ini untuk mempromosikan ejekan sederhana. Misalnya, alih-alih iterator, seseorang dapat menggunakan Iterable atau hanya koleksi. Mereka menawarkan cara-cara stubbing yang alami (misalnya menggunakan koleksi asli). Dalam skenario yang jarang terjadi, menghentikan panggilan berturut-turut dapat berguna, meskipun:

when(mock.someMethod("some arg"))
   .thenThrow(new RuntimeException())
  .thenReturn("foo");

//First call: throws runtime exception:
mock.someMethod("some arg");

//Second call: prints "foo"
System.out.println(mock.someMethod("some arg"));

Jadi dalam kasus Anda, Anda ingin:

when(myMock.doTheCall())
   .thenReturn("You failed")
   .thenReturn("Success");

25
Ini mengarahkan saya ke arah yang benar (terima kasih) untuk skenario saya yang berhubungan dengan metode void - dalam hal ini Anda perlu menggunakan gaya alternatif ...doThrow(new RuntimeException()).doNothing().when(myMock).doTheCall();
haggisandchips

38

Cara terpendek untuk menulis apa yang Anda inginkan adalah

when(myMock.doTheCall()).thenReturn("Success", "you failed");

Saat Anda memberikan beberapa argumen untuk thenReturnseperti ini, setiap argumen akan digunakan paling banyak sekali, kecuali untuk argumen terakhir, yang digunakan sebanyak yang diperlukan. Misalnya, dalam kasus ini, jika Anda melakukan panggilan 4 kali, Anda akan mendapatkan "Sukses", "Anda gagal", "Anda gagal", "Anda gagal".


22

Karena komentar yang berkaitan dengan ini sulit dibaca, saya akan menambahkan jawaban yang diformat.

Jika Anda mencoba melakukan ini dengan voidfungsi yang hanya mengeluarkan pengecualian, diikuti dengan langkah tanpa perilaku, Anda akan melakukan sesuatu seperti ini:

Mockito.doThrow(new Exception("MESSAGE"))
            .doNothing()
            .when(mockService).method(eq());

4

Untuk menambahkan ini dan jawaban ini , Anda juga dapat menggunakan loop untuk merangkai panggilan palsu. Ini berguna jika Anda perlu mengejek hal yang sama beberapa kali, atau mengejek dalam beberapa pola.

Misalnya (meskipun terlalu dibuat-buat):

import org.mockito.stubbing.Stubber;

Stubber stubber = doThrow(new Exception("Exception!"));
for (int i=0; i<10; i++) {
    if (i%2 == 0) {
        stubber.doNothing();
    } else {
        stubber.doThrow(new Exception("Exception"));
    }
}
stubber.when(myMockObject).someMethod(anyString());

Saya sebenarnya tidak tahu tentang Stubber ini dan merasa berguna, +1.
Mihai Morcov

Ini harus menjadi jawaban yang tepat jika Anda membutuhkan panggilan metode void.
db80

4

Saya memiliki situasi yang berbeda, saya ingin mengejek suatu voidfungsi untuk panggilan pertama dan menjalankannya secara normal pada panggilan kedua.

Ini bekerja untuk saya:

Mockito.doThrow(new RuntimeException("random runtime exception"))
       .doCallRealMethod()
       .when(spy).someMethod(Mockito.any());
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.