我试图让我的一个模拟对象抛出一个checked 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文档,他们只使用RuntimeException,是不是不可能从Mockito的模拟对象抛出受控异常?
检查List的Java API。
get(int index)方法被声明为只抛出IndexOutOfBoundException,它扩展了RuntimeException。
您试图告诉Mockito抛出一个异常SomeException(),该异常不适合由该特定方法调用抛出。
为了进一步澄清。
List接口没有提供从get(int index)方法抛出的受控异常,这就是Mockito失败的原因。
当您创建模拟列表时,Mockito将使用List.class的定义来创建它的模拟。
使用when(list.get(0))指定的行为。thenThrow(new SomeException())不匹配List API中的方法签名,因为get(int index)方法不抛出SomeException(),因此Mockito失败。
如果你真的想这样做,那么让Mockito抛出一个新的RuntimeException(),或者更好的是抛出一个新的ArrayIndexOutOfBoundsException(),因为API指定这是唯一要抛出的有效异常。
注意,通常情况下,Mockito允许抛出检查过的异常,只要异常在消息签名中声明了。例如,给定
class BarException extends Exception {
// this is a checked exception
}
interface Foo {
Bar frob() throws BarException
}
这样写是合法的:
Foo foo = mock(Foo.class);
when(foo.frob()).thenThrow(BarException.class)
然而,如果你抛出一个未在方法签名中声明的受控异常,例如。
class QuxException extends Exception {
// a different checked exception
}
Foo foo = mock(Foo.class);
when(foo.frob()).thenThrow(QuxException.class)
Mockito将在运行时失败,并给出一些误导性的通用消息:
Checked exception is invalid for this method!
Invalid: QuxException
这可能会导致您认为受控异常通常是不受支持的,但实际上Mockito只是试图告诉您该受控异常对于该方法无效。