246

我试图让我的一个模拟对象在调用特定方法时抛出一个检查异常。我正在尝试以下。

@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 文档,他们只使用MockitoRuntimeException是否无法从模拟对象中抛出已检查的异常?

4

5 回答 5

308

检查List的 Java API 。
get(int index)方法被声明为仅抛出IndexOutOfBoundExceptionwhich extends RuntimeException
您正试图告诉 Mockito 抛出一个无效的异常SomeException(),该异常不能由该特定方法调用抛出

进一步澄清。List接口不提供从方法中抛出的已检查异常,
这就是 Mockito 失败的原因。 当您创建模拟List时,Mockito 将使用List .class 的定义来创建它的模拟。 get(int index)

您使用 指定的行为与when(list.get(0)).thenThrow(new SomeException()) List API 中的方法签名不匹配,因为get(int index)方法不会抛出SomeException(),所以 Mockito 失败。

如果你真的想这样做,那么让 Mockito 抛出一个new RuntimeException()甚至更好的抛出一个new ArrayIndexOutOfBoundsException(),因为 API 指定这是唯一要抛出的有效异常。

于 2010-09-21T15:58:46.020 回答
173

一种解决方法是使用一种willAnswer()方法。

例如,以下工作(并且不抛出 aMockitoException但实际上Exception在这里根据需要抛出一个检查)使用BDDMockito

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

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

于 2018-01-15T10:24:48.520 回答
23

Kotlin 有解决方案:

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

给定来自哪里

导入 org.mockito.BDDMockito.given

于 2019-10-25T12:37:39.880 回答
14

请注意,通常,只要在消息签名中声明了异常,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 只是试图告诉您此已检查的异常对此方法无效。

于 2020-01-06T22:36:43.927 回答
3

这在 Kotlin 中对我有用:

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

注意:抛出除 Exception() 之外的任何已定义异常

于 2020-02-14T19:48:31.780 回答