我正在尝试让我的一个模拟对象在调用特定方法时抛出一个已检查的Exception。我正在尝试以下方法。
@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 {
}
然而,这会产生以下错误。
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
查看Mockito documentation,他们只使用RuntimeException
,是否无法使用Mockito从模拟对象中抛出已检查的异常?
答案 0 :(得分:165)
检查Java API List。声明get(int)方法只抛出扩展RuntimeException的IndexOutOfBoundException。您试图告诉Mockito抛出一个异常,该异常无法被该特定方法调用抛出。
进一步澄清。 List接口不提供从get()方法抛出的已检查异常,这就是Mockito失败的原因。当您创建模拟List时,Mockito使用List.class的定义来创建其模拟。您使用when(list.get(0)).thenThrow(new SomeException())
指定的行为与List.class中的方法签名不匹配,因此Mockito失败。如果你真的想要这样做,那么让Mockito抛出new RuntimeException()
甚至更好的抛出new ArrayIndexOutOfBoundsException()
,因为API指定这是唯一有效的异常抛出。
答案 1 :(得分:50)
解决方法是使用willAnswer()
方法。
例如,使用MockitoException
以下工作(并且不会抛出Exception
但实际上会根据需要抛出已检查的BDDMockito
:
given(someObj.someMethod(stringArg1)).willAnswer( invocation -> { throw new Exception("abc msg"); });
普通Mockito的等价物将使用doAnswer
方法
答案 2 :(得分:2)
这在Kotlin中对我有用:
when(list.get(0)).thenThrow(new ArrayIndexOutOfBoundsException());
注意:抛出除Exception()以外的所有已定义的异常
答案 3 :(得分:1)
Kotlin有解决方案:
Duplicate variable object name
给出的地方来自
导入org.mockito.BDDMockito.given