Mockito Bagaimana cara mengejek dan menyatakan pengecualian?

136

Saya menggunakan mockito dalam tes junit. Bagaimana Anda membuat pengecualian terjadi dan kemudian menyatakan bahwa ia memiliki (kode pseudo generik)

stackoverflow
sumber

Jawaban:

75

Solusi Gaya BDD (Diperbarui ke Java 8)

Mockito sendiri bukan solusi terbaik untuk menangani pengecualian, gunakan Mockito dengan Catch-Exception

Mockito + Catch-Exception + AssertJ

given(otherServiceMock.bar()).willThrow(new MyException());

when(() -> myService.foo());

then(caughtException()).isInstanceOf(MyException.class);

Kode sampel

Ketergantungan

MariuszS
sumber
2
Apa itu "pengecualian menangkap"? Punya tautan?
Duncan Jones
apa caughtException?
Saif Masadeh
Mengerti, itu berasal daricom.googlecode.catchexception.CatchException.caughtException;
Saif Masadeh
212

Untuk menjawab pertanyaan kedua Anda terlebih dahulu. Jika Anda menggunakan JUnit 4, Anda dapat membuat anotasi dengan tes Anda

@Test(expected=MyException.class)

untuk menegaskan bahwa pengecualian telah terjadi. Dan untuk "mengejek" pengecualian dengan mockito, gunakan

when(myMock.doSomething()).thenThrow(new MyException());
NilsH
sumber
2
pendekatan ini tidak dapat diterima untuk kasus ketika Anda menguji metode objek yang memiliki beberapa keadaan. Misalnya ada metode objek yang melempar pengecualian jika Anda menyebutnya yang kedua kalinya. Dan Anda perlu menguji untuk menguji apakah ia melempar pengecualian selama pemanggilan metode kedua, bukan yang pertama. Jika itu melempar MyException selama pemanggilan metode pertama (dalam tahap persiapan) maka harus gagal tes. Tetapi dengan pendekatan ini kami tidak dapat memeriksa selama panggilan metode pengecualian dilemparkan.
Sneg
Meskipun dalam kasus ini kita dapat menangkap pengecualian dari pemanggilan metode pertama dan membungkusnya dalam RuntimeException.
Sneg
29

Jika Anda ingin menguji pesan pengecualian juga, Anda dapat menggunakan JUnit's ExpectedException dengan Mockito:

@Rule
public ExpectedException expectedException = ExpectedException.none();

@Test
public void testExceptionMessage() throws Exception {
    expectedException.expect(AnyException.class);
    expectedException.expectMessage("The expected message");

    given(foo.bar()).willThrow(new AnyException("The expected message"));
}
Daniel Treiber
sumber
given()dari mana ini berasal?
Mohammad Faisal
Saya juga lebih suka menggunakan aturan @, karena dengan cara ini saya bisa menguji pesan yang diharapkan atau penyebab atau hal-hal lain yang berkaitan dengan pengecualian. Untuk memeriksa penyebab pengecualian, saya menggunakan: expectedException.expectCause (Mockito.sameInstance (expectedException)) atau expectedException.expectCause (Mockito.instanceOf (MyException.class)) dan beberapa lainnya yang berguna.
Crenguta S
19

Jawaban yang diperbarui untuk 06/19/2015 (jika Anda menggunakan java 8)

Cukup gunakan assertj

Menggunakan assertj-core-3.0.0 + Java 8 Lambdas

@Test
public void shouldThrowIllegalArgumentExceptionWhenPassingBadArg() {
assertThatThrownBy(() -> myService.sumTingWong("badArg"))
                                  .isInstanceOf(IllegalArgumentException.class);
}

Referensi: http://blog.codeleak.pl/2015/04/junit-testing-exceptions-with-java-8.html

Selwyn
sumber
bekerja untuk saya ... Juga kita dapat memeriksa pesan pengecualian juga .assertThatThrownBy (() -> myService.sumTingWong ("badArg")). hasMessage ("test") .isInstanceOf (IllegalArgumentException.class);
Sritam Jagadev
17

Jika Anda menggunakan JUnit 4, dan Mockito 1.10.x anotasi metode pengujian Anda dengan:

@Test(expected = AnyException.class)

dan untuk membuang penggunaan pengecualian yang Anda inginkan:

Mockito.doThrow(new AnyException()).when(obj).callAnyMethod();
Prashant Kumar
sumber
16

Buat pengecualian terjadi seperti ini:

when(obj.someMethod()).thenThrow(new AnException());

Verifikasi itu telah terjadi baik dengan menyatakan bahwa tes Anda akan mengeluarkan pengecualian seperti itu:

@Test(expected = AnException.class)

Atau dengan verifikasi tiruan normal:

verify(obj).someMethod();

Opsi terakhir diperlukan jika pengujian Anda dirancang untuk membuktikan kode perantara menangani pengecualian (yaitu pengecualian tidak akan dilempar dari metode pengujian Anda).

Duncan Jones
sumber
Apakah verifypanggilan tersebut menyatakan pengecualian?
NilsH
@NilsH Tidak. Tapi asalkan whenklausa itu benar, itu pasti telah melemparkan pengecualian.
Duncan Jones
10

Gunakan doTrow Mockito dan kemudian menangkap pengecualian yang diinginkan untuk menegaskan itu dibuang kemudian.

@Test
public void fooShouldThrowMyException() {
    // given
    val myClass = new MyClass();
    val arg = mock(MyArgument.class);
    doThrow(MyException.class).when(arg).argMethod(any());
    Exception exception = null;

    // when
    try {
        myClass.foo(arg);
    } catch (MyException t) {
        exception = t;
    }

    // then
    assertNotNull(exception);
}
Rodrigo Martins de Oliveira
sumber
5

Menggunakan mockito, Anda dapat membuat pengecualian terjadi.

when(testingClassObj.testSomeMethod).thenThrow(new CustomException());

Menggunakan Junit5, Anda dapat menyatakan pengecualian, menegaskan apakah yang eksepsi dilemparkan ketika metode pengujian dipanggil.

@Test
@DisplayName("Test assert exception")
void testCustomException(TestInfo testInfo) {
    final ExpectCustomException expectEx = new ExpectCustomException();

     InvalidParameterCountException exception = assertThrows(InvalidParameterCountException.class, () -> {
            expectEx.constructErrorMessage("sample ","error");
        });
    assertEquals("Invalid parametercount: expected=3, passed=2", exception.getMessage());
}

Temukan sampel di sini: sebutkan pengecualian junit

Anupama Boorlagadda
sumber
Terima kasih! Bekerja untuk saya
HariKishore
1

Tidak terkait dengan mockito, orang dapat menangkap pengecualian dan menegaskan propertinya. Untuk memverifikasi bahwa pengecualian itu benar-benar terjadi, nyatakan kondisi yang salah dalam blok coba setelah pernyataan yang melempar pengecualian.

belut ghEEz
sumber
Tanggapan @MariuszS dengan benar menjawab apa yang Anda katakan tidak terkait dengan Mockito
pringi
@ Pringi Terima kasih, saya melihat bahwa pertanyaan yang bersangkutan mengejek pengecualian dan menangkapnya. Saya bertanya-tanya apakah ini tergantung pada perilaku kode yang diuji.
belut ghEEz
1

Atau jika pengecualian Anda dilempar dari konstruktor kelas:

@Rule
public ExpectedException exception = ExpectedException.none();

@Test
public void myTest() {    

    exception.expect(MyException.class);
    CustomClass myClass= mock(CustomClass.class);
    doThrow(new MyException("constructor failed")).when(myClass);  

}
JediCate
sumber
-1

Menegaskan dengan pesan pengecualian:

    try {
        MyAgent.getNameByNode("d");
    } catch (Exception e) {
        Assert.assertEquals("Failed to fetch data.", e.getMessage());
    }
Sam
sumber
Jika ditulis seperti ini, ketika tidak ada pengecualian dilemparkan, tes akan tetap berlalu . Itulah yang ingin kita hindari sejak awal
Christian Lim