使用Mockito模拟对象抛出异常

3

有些东西告诉我,我做错了什么......应该不会这么难。

我有一个依赖于某个内部类的类。我通过一个受保护的方法创建它,以便我可以在测试中重写它并提供一个模拟对象。我知道要让Mockito模拟对象从void方法中抛出异常,我必须使用doThrow。

但是我的问题是,编译器抱怨对Mockito.doThrow()的调用会抛出RuntimeException......所以我必须在设置模拟的方法中添加throws子句。这是Mockito本身的错误吗?doThrow声明了将来应该发生的事情,而不是在设置模拟期间发生的事情。

我的OuterClass看起来像...

public class OuterClass {
  protected InnerClass inner;
  protected void createInner() { inner = new InnerClass(); }
  protected doSomething() {
    try {
      inner.go();
    } catch (RuntimeException re) {
      throw new MyException("computer has caught fire");
    }
  }
}

我的测试代码看起来像这样...
@Test(expected = MyException.class)
public void testSomething() {
  OuterClass outer = new TestOuterClass();
  outer.doSomething();
}

public static class TestOuterClass extends OuterClass {
  @Override
  public void createInner() {
    InnerClass mock = Mockito.mock(InnerClass.mock);
    Mockito.doThrow(new RuntimeException("test")).when(mock).go();  // PROBLEM
    inner = mock;
  }
}
1个回答

1

请问您能否确认编译器是否真的在抱怨一个RuntimeException吗?

RuntimeException的问题在于它在编译时不应该有影响。我怀疑编译器实际上是在抱怨MyException - 我假设这是一个被编译器注意到并由doSomething()方法抛出的已检查异常。您应该能够简单地将throws MyException添加到测试方法中,然后由测试运行程序捕获。由于这是预期的,测试运行程序将通过。


是的,我的错误。它真正抱怨的是MyException,就像你建议的那样。InnerClass.go() 声明要抛出 MyException(我在上面的代码中省略了这一点)。但是 OuterClass.createInner() 没有声明。我认为问题不是 Mockito.doThrow() 引起的...而是最后调用 .go() 的问题。因此,即使 @test 方法已经声明了 throws MyException,这也没有帮助。 - DaveyBob
啊哈!我解决了。我只需要在try / catch中包装我的doThrow...go()代码,以使其对create方法不可见。但是当调用create方法时,它实际上会调用mock,并且确实会获取并捕获RuntimeException。 - DaveyBob

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