我是Mockito的新手,我遍历了此示例,但是当它在方法的第一行调用doNothing()时,有一个步骤我不理解:

@Test(expected = RuntimeException.class)
public void testConsecutiveCalls() throws Exception(){
  doNothing().doThrow(Exception.class).when(b).voidMethod();
  a.usesVoidMethod()
  verify(b).voidMethod();
  a.usesVoidMethod()
}


我确实知道,第一次调用voidMehtod()时不返回任何内容,而第二次给出异常。

但是,如果我们删除doNothing.doThrow(Exception.class).when(b).voidMethod();,测试是否仍然有效,是否会测试我们想要测试的方法第二次抛出异常?

最佳答案

为了方便参考,列出了几点:


模拟的默认行为是每次都返回适当的伪值,通常为零,null或空字符串。间谍的默认行为是调用间谍的实际实现。当然,通过@MockMockito.mock的参数,您可以使用任意Answer或Mockito的standardadditional答案中的任何一个。
当多个动作作为一条链的一部分给出时,Mockito将依次执行每个动作,并永远重复最后的动作。

// calls to foo.bar() return 1, 2, 3, 3, 3...
doReturn(1).thenReturn(2, 3).when(foo).bar();


请注意,这是在同一链中;最近定义的匹配链会获胜,因此单独的语句不会有相同的效果。

doReturn(1).thenReturn(2).when(foo).baz();
doReturn(3).thenReturn(4).when(foo).baz();
// calls return 3, 4, 4, 4... because the first chain is entirely overridden.

然后,doNothing的大部分价值来自覆盖默认行为或在链中设置操作。


因此,测试要尝试执行的是第一次doNothing以便验证成功,然后第二次doThrow满足预期的异常。尽管失败的verify因为Mockito's errors subclass Error and not Exception而会(正确地)使测试失败,但您没错,删除doNothing仍会通过在第一次调用a.usesVoidMethod()时抛出异常来使测试通过。尽管这对于测试来说已经足够了(毕竟,您可以在测试本身中看到doNothing),但是更强大的测试可能看起来像这样:

@Test
public void testConsecutiveCalls() throws Exception(){
  doNothing().doThrow(SomeKnownException.class).when(b).voidMethod();
  a.usesVoidMethod();
  verify(b).voidMethod();
  try {
    a.usesVoidMethod();
    fail();
  } catch (SomeKnownException expected) { /* OK */ }
}

09-28 06:39