问题

我正在尝试让我的一个模拟对象在调用特定方法时抛出一个已检查的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的模拟对象中抛出已检查的异常?


#1 热门回答(133 赞)

检查Java API for List。声明get(int)方法只抛出IndexOutOfBoundException,它扩展了RuntimeException。你试图告诉Mockito抛出一个异常,该异常无法被该特定方法调用抛出。

进一步澄清。 List接口不提供从get()方法抛出的已检查异常,这就是Mockito失败的原因。当你创建模拟List时,Mockito使用List.class的定义来创建其模拟。你使用when(list.get(0)).thenThrow(new SomeException())指定的行为与List.class中的方法签名不匹配,因此Mockito失败。如果你真的想这样做,那么让Mockito抛出anew RunTimeException()甚至更好抛出anew ArrayIndexOutOfBoundsException(),因为API指定这是唯一有效的异常抛出。


#2 热门回答(21 赞)

解决方法是使用awillAnswer()方法。

例如,以下工作(并且不会抛出aMockitoException但实际上抛出了这里需要的checkedException)usingBDDMockito

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

普通Mockito的等价物将使用doAnswer方法


原文链接