拦截已检查异常:如何处理异常

3

我正在使用Junit 4和Mockito,并且我想为方法调用设置存根,以便它抛出异常:

doThrow(MyException.class).when(myObject).foo();

问题在于,MyException 是一个已检查的异常,所以这个语句中对 foo() 的调用会导致编译器抱怨我必须要么处理异常,要么在我的方法中添加 throws 子句。
所以我想知道处理这种情况的正确方式是什么? 我目前的想法是:
  1. 我使用的方法不对,有更好的方法。
  2. 只需在测试方法中添加 throws MyException
  3. 将调用提取到另一个仅吞噬异常的方法中
例如:
private void givenFooThrowsAnException(MyObject myObject) {
    try {
        doThrow(MyException.class).when(myObject).foo();
    } catch (MyException e) {
        // Required to stub a checked exception
    }
}

检查foo()方法的签名,它是否应该抛出一个受检异常?如果不是,则您正在错误地使用它。在测试中应该抛出一个RuntimeException。 - Manoj
5
我会选择方案#2。在测试方法中添加throws Exception是没有问题的吗? - user626607
1
myObject是我注入到被测试类中的一个依赖项。我正在测试被测试类所采取的两条路径,其中之一发生在myObject.foo()抛出MyException(这是一个已检查异常)时。也许我误解了你的观点,但我的问题不在于我说doThrow(MyException.class),而是编译器在这里看到了对foo()的调用,它会抛出必须处理的异常。但由于这只是设置存根,异常实际上并不会被抛出。 - DaveJohnston
3
因此,如果引发了异常,就表示出现了严重问题,您希望测试失败。因此,请在测试方法签名中添加throws MyException子句,并让JUnit在引发异常时使测试失败。 - JB Nizet
1个回答

2

尽管存根强制你处理已检查异常,但实际上它永远不会抛出该异常。最优雅的方法是声明测试方法抛出该异常。

但这种方法有一个注意点。如果你的测试实际上通过在 @Test 注解中声明它来验证已检查异常是否被抛出。

@Test(expected=MyException.class)
public void test...() throws MyException {
    //...
}

如果你的桩对象(stub)出现问题并抛出了受检异常,那么测试就会通过,但实际上应该是失败的。或者,你可以使用未受检异常来解决这个问题。请参考这篇文章

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接