Java Mockito,doNothing() When() 的用法

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/39822532/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-11 21:28:08  来源:igfitidea点击:

Mockito, Usages of doNothing() When()

javaunit-testingmockito

提问by MIKE

I'm new to Mockito, and I went over this example but there is one step that I do not understand when it calls doNothing()on the first line of the method:

我是 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()
}

I do understand that when the first time voidMehtod()is called is returning nothing and in the second time it is giving an exception.

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

But if we remove the doNothing.doThrow(Exception.class).when(b).voidMethod();, won't the test still be valid and will test what we want to test that the method throw an exception in the second time?

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

回答by Niklas P

The doNothingmethod doesn't change the behaviour of a mocked' method, but the declaration of thedoThrowdoes. If you have a spy and don't want a method to be executed, thendoNothing` will change the behaviour.

doNothing方法不会改变mocked' method, but the declaration of thedoThrow does. If you have a spy and don't want a method to be executed, thendoNothing` 的行为会改变行为。

回答by Jeff Bowman

A few points, numbered just for ease of reference:

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

  1. The default behavior of a mockis to return an appropriate dummy value every time, often zero, null, or an empty string. The default behavior of a spy is to call the spy's real implementation. Of course, through parameters to @Mockor Mockito.mock, you can use an arbitrary Answer or any of Mockito's standardor additionalanswers.

  2. When multiple actions are given as a part of a chain, Mockito will do each action in sequence and forever repeat the final action.

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

    Note that this is within the same chain; the most-recently-defined matching chain wins, so separate statements wouldn't have the same effect.

    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.
    
  3. doNothing, then, gets most of its value from either overriding default behavioror setting up an action in a chain.

  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();
    

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

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

So what the test is tryingto do is to doNothingthe first time such that the verification will succeed, and then doThrowthe second time to satisfy the expected exception. Though a failed verifywould (correctly) fail the test because Mockito's errors subclass Error and not Exception, you're right that a removal of the doNothingwould still cause the test to pass by throwing the exception on the first call to a.usesVoidMethod(). Though this is fine enough for the test--after all, you can see the doNothingin the test itself--a more robust test might look like this:

所以测试试图做的是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 */ }
}