Mockito วิธีการเยาะเย้ยและยืนยันข้อยกเว้น?


140

ฉันใช้ม็อกกิโตในการทดสอบจูนิท คุณจะสร้างข้อยกเว้นได้อย่างไรและยืนยันว่ามี (รหัสหลอกทั่วไป)

คำตอบ:


75

BDD Style Solution (อัปเดตเป็น Java 8)

Mockitoเพียงอย่างเดียวไม่ใช่ทางออกที่ดีที่สุดสำหรับการจัดการข้อยกเว้นให้ใช้MockitoกับCatch-Exception

Mockito + Catch-Exception + AssertJ

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

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

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

โค้ดตัวอย่าง

การพึ่งพา


2
"catch-except" คืออะไร? มีลิงค์?
Duncan Jones

คือcaughtExceptionอะไร
Saif Masadeh

เข้าใจแล้วมันมาจากcom.googlecode.catchexception.CatchException.caughtException;
Saif Masadeh

216

เพื่อตอบคำถามที่สองของคุณก่อน หากคุณใช้ JUnit 4 คุณสามารถใส่คำอธิบายประกอบการทดสอบของคุณด้วยไฟล์

@Test(expected=MyException.class)

เพื่อยืนยันว่ามีข้อยกเว้นเกิดขึ้น และหากต้องการ "เยาะเย้ย" ข้อยกเว้นของม็อกโตะให้ใช้

when(myMock.doSomething()).thenThrow(new MyException());

3
วิธีนี้ไม่สามารถยอมรับได้ในกรณีที่คุณกำลังทดสอบวิธีการของวัตถุที่มีสถานะบางอย่าง ตัวอย่างเช่นมีเมธอดอ็อบเจ็กต์ที่ทำให้เกิดข้อยกเว้นหากคุณเรียกมันเป็นครั้งที่สอง และคุณต้องทดสอบเพื่อทดสอบว่ามีข้อยกเว้นในระหว่างการเรียกวิธีที่สองไม่ใช่ครั้งแรก หากมีการพ่น MyException ในระหว่างการเรียกใช้วิธีแรก (ในขั้นตอนการเตรียมการ) การทดสอบจะล้มเหลว แต่ด้วยวิธีนี้เราไม่สามารถตรวจสอบได้ในระหว่างที่วิธีการเรียกใช้ข้อยกเว้นถูกโยนทิ้ง
Sneg

แม้ว่าในกรณีนี้เราสามารถตรวจจับข้อยกเว้นจากการเรียกวิธีแรกและรวมไว้ใน RuntimeException
Sneg

29

หากคุณต้องการทดสอบข้อความข้อยกเว้นคุณสามารถใช้คาดว่าจะได้รับการยกเว้นของ JUnit กับ 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"));
}

given()มันมาจากไหน?
Mohammad Faisal


ฉันชอบใช้ @Rule ด้วยเพราะวิธีนี้ฉันสามารถทดสอบข้อความที่คาดหวังหรือสาเหตุหรือสิ่งอื่น ๆ ที่เกี่ยวข้องกับข้อยกเว้นได้ สำหรับการตรวจสอบสาเหตุของข้อยกเว้นฉันใช้: expectedException.expectCause (Mockito.sameInstance (expectedException)) หรือ expectedException.expectCause (Mockito.instanceOf (MyException.class)) และอื่น ๆ อีกสองสามอย่างที่มีประโยชน์
Crenguta S

19

คำตอบที่อัปเดตสำหรับ 06/19/2015 (หากคุณใช้ java 8)

เพียงใช้ assertj

ใช้ assertj-core-3.0.0 + Java 8 Lambdas

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

อ้างอิง: http://blog.codeleak.pl/2015/04/junit-testing-exceptions-with-java-8.html


ได้ผลสำหรับฉัน ... นอกจากนี้เราสามารถตรวจสอบข้อความยกเว้นได้เช่นกันassertThatThrownBy (() -> myService.sumTingWong ("badArg")) hasMessage ("test") .isInstanceOf (IllegalArgumentException.class);
Sritam Jagadev

17

หากคุณใช้ JUnit 4 และ Mockito 1.10.x ใส่คำอธิบายประกอบวิธีการทดสอบของคุณด้วย:

@Test(expected = AnyException.class)

และโยนข้อยกเว้นที่คุณต้องการใช้:

Mockito.doThrow(new AnyException()).when(obj).callAnyMethod();

16

ทำให้ข้อยกเว้นเกิดขึ้นดังนี้:

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

ตรวจสอบว่าเกิดอะไรขึ้นโดยยืนยันว่าการทดสอบของคุณจะทำให้เกิดข้อยกเว้นดังกล่าว:

@Test(expected = AnException.class)

หรือโดยการตรวจสอบจำลองปกติ:

verify(obj).someMethod();

จำเป็นต้องใช้ตัวเลือกหลังหากการทดสอบของคุณออกแบบมาเพื่อพิสูจน์ว่ารหัสกลางจัดการกับข้อยกเว้น (กล่าวคือข้อยกเว้นจะไม่ถูกโยนออกจากวิธีการทดสอบของคุณ)


การverifyโทรยืนยันข้อยกเว้นหรือไม่
NilsH

@NilsH ไม่ได้ แต่ถ้าwhenประโยคถูกต้องก็ต้องมีข้อยกเว้น
Duncan Jones

10

ใช้doThrow ของ Mockitoแล้วจับข้อยกเว้นที่ต้องการเพื่อยืนยันว่าถูกโยนทิ้งในภายหลัง

@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);
}

6

การใช้ม็อกกิโตคุณสามารถทำให้ข้อยกเว้นเกิดขึ้นได้

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

ใช้ Junit5 คุณสามารถยืนยันข้อยกเว้นอ้างว่าที่ยกเว้นจะโยนเมื่อวิธีการทดสอบจะถูกเรียก

@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());
}

ค้นหาตัวอย่างได้ที่นี่: ยืนยันข้อยกเว้น junit


ขอบคุณ! ทำงานให้ฉัน
HariKishore

2

หรือถ้าข้อยกเว้นของคุณถูกโยนออกจากตัวสร้างของคลาส:

@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);  

}

1

ไม่เกี่ยวข้องกับ mockito เราสามารถจับข้อยกเว้นและยืนยันคุณสมบัติของมันได้ หากต้องการตรวจสอบว่ามีข้อยกเว้นเกิดขึ้นให้ยืนยันเงื่อนไขเท็จภายในบล็อกการลองหลังจากคำสั่งที่แสดงข้อยกเว้น


การตอบสนองของ @MariuszS ตอบได้อย่างถูกต้องว่าสิ่งที่คุณกำลังพูดนั้นไม่เกี่ยวข้องกับ Mockito
pringi

@pringi ขอบคุณฉันเห็นว่าคำถามที่เกี่ยวข้องทั้งการเยาะเย้ยข้อยกเว้นและการจับมัน ฉันสงสัยว่านี่ขึ้นอยู่กับพฤติกรรมของโค้ดที่ทดสอบหรือไม่
eel ghEEz

-1

ยืนยันด้วยข้อความยกเว้น:

    try {
        MyAgent.getNameByNode("d");
    } catch (Exception e) {
        Assert.assertEquals("Failed to fetch data.", e.getMessage());
    }

ถ้าเขียนเช่นนี้เมื่อมีไม่มีข้อยกเว้นโยนการทดสอบจะยังคงผ่าน ซึ่งเป็นสิ่งที่เราต้องการหลีกเลี่ยงในตอนแรก
Christian Lim
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.