Mockito Làm thế nào để chế nhạo và khẳng định một ngoại lệ ném?


136

Tôi đang sử dụng mockito trong một bài kiểm tra Junit. Làm thế nào để bạn thực hiện một ngoại lệ xảy ra và sau đó khẳng định rằng nó có (mã giả chung)

Câu trả lời:


75

Giải pháp kiểu BDD (Cập nhật lên Java 8)

Một mình Mockito không phải là giải pháp tốt nhất để xử lý các trường hợp ngoại lệ, hãy sử dụng Mockito với Catch-Exception

Mockito + Catch-Exception + AssertJ

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

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

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

Mã mẫu

Phụ thuộc


2
"Ngoại lệ bắt" là gì? Có một liên kết?
Duncan Jones

những gì caughtException?
Saif Masadeh

com.googlecode.catchexception.CatchException.caughtException;
Hiểu

211

Để trả lời câu hỏi thứ hai của bạn đầu tiên. Nếu bạn đang sử dụng JUnit 4, bạn có thể chú thích bài kiểm tra của mình với

@Test(expected=MyException.class)

để khẳng định rằng một ngoại lệ đã xảy ra. Và để "chế nhạo" một ngoại lệ với mockito, hãy sử dụng

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

2
Cách tiếp cận này không được chấp nhận trong trường hợp khi bạn đang thử nghiệm phương pháp của một đối tượng có một số trạng thái. Ví dụ, có một phương thức đối tượng ném ngoại lệ nếu bạn gọi nó là lần thứ hai. Và bạn cần kiểm tra để kiểm tra xem nó có ném ngoại lệ trong lần gọi phương thức thứ hai không, không phải phương thức thứ nhất. Nếu nó ném MyException trong lần gọi phương thức đầu tiên (trong giai đoạn chuẩn bị) thì nó sẽ thất bại trong bài kiểm tra. Nhưng với phương pháp này, chúng tôi không thể kiểm tra xem phương thức nào gọi ngoại lệ được ném.
Sneg

Mặc dù trong trường hợp này, chúng ta có thể bắt ngoại lệ từ lệnh gọi phương thức đầu tiên và gói nó trong RuntimeException.
Sneg

29

Nếu bạn cũng muốn kiểm tra thông báo ngoại lệ, bạn có thể sử dụng ExpectedException của JUnit với 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()Trường hợp nào này đến từ đâu?
Mohammad Faisal


Tôi cũng thích sử dụng @Rule, vì cách này tôi có thể kiểm tra tin nhắn dự kiến ​​hoặc nguyên nhân hoặc các nội dung khác liên quan đến ngoại lệ. Để kiểm tra nguyên nhân của ngoại lệ, tôi sử dụng: lookingException.ExectCause (Mockito.sameInstance (kỳ vọng ngoại lệ)) hoặc kỳ vọngException.ExectCause (Mockito.instanceOf (MyException. Class)) và một vài thứ khác có ích.
Crenguta S

19

Câu trả lời được cập nhật cho ngày 19 tháng 6 năm 2015 (nếu bạn đang sử dụng java 8)

Chỉ cần sử dụng assertj

Sử dụng assertj-core-3.0.0 + Java 8 Lambdas

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

Tham khảo: http://blog.codeleak.pl/2015/04/junit-testing-exceptions-with-java-8.html


đã làm việc cho tôi ... Ngoài ra, chúng tôi cũng có thể kiểm tra thông báo ngoại lệ.assertThatThrownBy (() -> myService.sumTingWong ("badArg")). hasMessage ("test") .isInstanceOf (IllegalArgumentException.)
Sritam Jagadev

17

Nếu bạn đang sử dụng JUnit 4 và Mockito 1.10.x Chú thích phương pháp kiểm tra của bạn với:

@Test(expected = AnyException.class)

và để sử dụng ngoại lệ mong muốn của bạn:

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

16

Làm cho ngoại lệ xảy ra như thế này:

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

Xác minh nó đã xảy ra hoặc bằng cách khẳng định rằng bài kiểm tra của bạn sẽ đưa ra một ngoại lệ như vậy:

@Test(expected = AnException.class)

Hoặc bằng cách xác minh giả thông thường:

verify(obj).someMethod();

Tùy chọn thứ hai là bắt buộc nếu thử nghiệm của bạn được thiết kế để chứng minh mã trung gian xử lý ngoại lệ (nghĩa là ngoại lệ sẽ không bị ném khỏi phương thức thử nghiệm của bạn).


Liệu verifycuộc gọi có khẳng định ngoại lệ?
NilsH

@NilsH Không. Nhưng với whenđiều kiện là đúng, nó phải có một ngoại lệ.
Duncan Jones

10

Sử dụng doThrow của Mockito và sau đó bắt ngoại lệ mong muốn để khẳng định nó được ném sau đó.

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

5

Sử dụng mockito, bạn có thể làm cho ngoại lệ xảy ra.

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

Sử dụng Junit5, bạn có thể xác nhận ngoại lệ, xác nhận xem ngoại lệ đó có bị ném khi phương thức kiểm tra được gọi hay không.

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

Tìm một mẫu ở đây: khẳng định ngoại lệ


Cảm ơn ! Làm việc cho tôi
HariKishore

1

Không liên quan đến mockito, người ta có thể bắt ngoại lệ và khẳng định tính chất của nó. Để xác minh rằng ngoại lệ đã xảy ra, hãy xác nhận một điều kiện sai trong khối thử sau khi tuyên bố ném ngoại lệ.


@MariuszS trả lời đúng câu trả lời của bạn không liên quan đến Mockito
pringi

@pringi Cảm ơn, tôi thấy rằng câu hỏi liên quan đến cả việc chế nhạo một ngoại lệ và bắt nó. Tôi tự hỏi mặc dù điều này phụ thuộc vào bất kỳ hành vi nào của mã được thử nghiệm.
lươn ghEEz

1

Hoặc nếu ngoại lệ của bạn được ném từ hàm tạo của một lớp:

@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

Khẳng định bằng tin nhắn ngoại lệ:

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

Nếu được viết như thế này, khi không có ngoại lệ được ném, bài kiểm tra vẫn sẽ vượt qua . Đó là những gì chúng tôi muốn tránh ở nơi đầu tiên
Christian Lim
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.