Mockito,doNothing() When() 的用法

MIK*_*IKE 2 java unit-testing mockito

我是 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()
}
Run Code Online (Sandbox Code Playgroud)

我确实明白,当第一次voidMehtod()被调用时什么都不返回,而在第二次时它给出了一个异常。

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

Jef*_*ica 5

几点,编号只是为了方便参考:

  1. 模拟的默认行为是每次都返回一个适当的虚拟值,通常是零null、 或空字符串。间谍的默认行为是调用间谍的真实实现。当然,通过@Mock或 的参数Mockito.mock,您可以使用任意答案或任何 Mockito 的标准附加答案。

  2. 当多个动作作为链的一部分给出时,Mockito 将按顺序执行每个动作并永远重复最后的动作。

    // calls to foo.bar() return 1, 2, 3, 3, 3...
    doReturn(1).thenReturn(2, 3).when(foo).bar();
    
    Run Code Online (Sandbox Code Playgroud)

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

    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.
    
    Run Code Online (Sandbox Code Playgroud)
  3. doNothing,然后,通过覆盖默认行为在链中设置操作来获取其大部分价值。

所以测试试图做的是doNothing第一次使验证成功,然后doThrow第二次满足预期的异常。尽管失败verify会(正确地)使测试失败,因为Mockito 的错误子类 Error 而不是 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 */ }
}
Run Code Online (Sandbox Code Playgroud)