ném ngoại lệ được kiểm tra từ giả với Mockito


173

Tôi đang cố gắng để một trong những đối tượng bị chế giễu của mình ném Ngoại lệ được kiểm tra khi một phương thức cụ thể được gọi. Tôi đang thử như sau.

@Test(expectedExceptions = SomeException.class)
public void throwCheckedException() {
    List<String> list = mock(List.class);
    when(list.get(0)).thenThrow(new SomeException());
    String test = list.get(0);
}

public class SomeException extends Exception {
}

Tuy nhiên, điều đó tạo ra lỗi sau.

org.testng.TestException: 
Expected exception com.testing.MockitoCheckedExceptions$SomeException but got org.mockito.exceptions.base.MockitoException: 
Checked exception is invalid for this method!
Invalid: com.testing.MockitoCheckedExceptions$SomeException

Nhìn vào tài liệu Mockito , họ chỉ sử dụng RuntimeException, không thể ném Ngoại lệ được kiểm tra từ một đối tượng giả với Mockito?

Câu trả lời:


221

Kiểm tra API Java cho danh sách .
Các get(int index)phương pháp được khai báo để ném chỉ IndexOutOfBoundExceptionkéo dài RuntimeException.
Bạn đang cố gắng nói với Mockito để ném một ngoại lệ SomeException()đó là không hợp lệ được ném bởi đó gọi phương thức đặc biệt .

Để làm rõ hơn.
Các Danh sách giao diện không cung cấp cho một ngoại lệ kiểm tra để được ném từ các get(int index)phương pháp và đó là lý do tại sao Mockito là không.
Khi bạn tạo Danh sách giả , Mockito sẽ sử dụng định nghĩa của Danh sách. Lớp để tạo giả.

Hành vi bạn đang chỉ định với when(list.get(0)).thenThrow(new SomeException()) chữ ký phương thức không khớp với API danh sách , vì get(int index)phương thức không némSomeException() nên Mockito không thành công.

Nếu bạn thực sự muốn làm điều này, thì hãy nhờ Mockito ném new RuntimeException()hoặc thậm chí tốt hơn ném new ArrayIndexOutOfBoundsException()vì API xác định rằng đó là Ngoại lệ hợp lệ duy nhất được ném.


Mặc dù mã thực sự của tôi không thực sự sử dụng Danh sách, câu trả lời của bạn cũng áp dụng cho cuộc gọi phương thức đó. Tôi đã chế giễu phương pháp sai. Cảm ơn bạn.
Arthur Maltson

2
thêm: Mocktio sẽ không phàn nàn nếu bạn thực hiện một phương pháp mà không có bất kỳ vật ném nào, nhưng bạn cũng sẽ có ngoại lệ này
dwana

8
Đối với Kotliners: Kotlin không kiểm tra ngoại lệ, do đó bạn thường không thể khai báo (trong chữ ký hàm) rằng hàm ném ngoại lệ. Tuy nhiên, bạn có thể chú thích hàm với Throwschú thích để làm cho trình biên dịch tạo mã byte tương tự như khai báo các cú ném trong mã Java tương đương. Xem [tại đây] ( kotlinlang.org/api/latest/jvm/stdlib/kotlin.jvm/-throws/ Lỗi ) để biết thêm chi tiết.
Javad Sadeqzadeh

1
Kiểm tra này được thi hành kể từ khi phát hành Mockito 2.11.0 (xem 2.10.3) .
JJD

105

Một cách giải quyết là sử dụng một willAnswer()phương pháp.

Ví dụ: các tác phẩm sau (và không ném MockitoExceptionnhưng thực sự ném một kiểm tra Exceptiontheo yêu cầu ở đây) bằng cách sử dụng BDDMockito:

given(someObj.someMethod(stringArg1)).willAnswer( invocation -> { throw new Exception("abc msg"); });

Tương đương với Mockito đơn giản sẽ sử dụng doAnswerphương thức


9
hoặc sử dụng willAnswer( invocation -> { throw new Exception("abc msg"); }).given(someObj).someMethod(stringArg1);khi phương thức trả về void.
Julien Kronegg

9
hoặc sử dụng khi (someObj.someMethod (stringArg1)). thenAnswer (invocation -> {throw new Exception ("abc dir");});
Dmitri Algazin

Cách giải quyết tuyệt vời, cảm ơn! Đối với những người yêu thích muốn (1) sử dụng liền mạch như một chức năng mở rộng và (2) có thể vượt qua một số đối số như willThrow()bình thường cho phép, tôi đã viết một Gist
David Ferrand

2
hoặc doAnswertừnhaarman.mockitokotlin2
hmac

6

Lưu ý rằng nói chung, Mockito không cho phép ném các ngoại lệ được kiểm tra miễn là ngoại lệ được khai báo trong chữ ký tin nhắn. Chẳng hạn, đã cho

class BarException extends Exception {
  // this is a checked exception
}

interface Foo {
  Bar frob() throws BarException
}

nó là hợp pháp để viết:

Foo foo = mock(Foo.class);
when(foo.frob()).thenThrow(BarException.class)

Tuy nhiên, nếu bạn ném một ngoại lệ được kiểm tra không được khai báo trong chữ ký phương thức, vd

class QuxException extends Exception {
  // a different checked exception
}

Foo foo = mock(Foo.class);
when(foo.frob()).thenThrow(QuxException.class)

Mockito sẽ thất bại trong thời gian chạy với thông điệp chung chung, hơi sai lệch:

Checked exception is invalid for this method!
Invalid: QuxException

Điều này có thể khiến bạn tin rằng đó kiểm tra ngoại lệ nói chung là không được hỗ trợ, nhưng trên thực tế Mockito chỉ cố gắng để cho bạn biết rằng đây là ngoại lệ kiểm tra là không hợp lệ cho phương pháp này .


5

Có giải pháp với Kotlin:

given(myObject.myCall()).willAnswer {
    throw IOException("Ooops")
}

Nơi được đưa ra đến từ

nhập org.mockito.BDDMockito.given


1

Điều này làm việc cho tôi trong Kotlin:

when(list.get(0)).thenThrow(new ArrayIndexOutOfBoundsException());

Lưu ý: Ném bất kỳ ngoại lệ được xác định nào khác ngoài Ngoại lệ ()


Chỉ cần những gì tôi đang tìm kiếm, có thể ném bất kỳ Ngoại lệ nào khác ngoàiException
Naeem Sarfraz
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.