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
Mockito, Usages of doNothing() When()
提问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 doNothing
method doesn't change the behaviour of a mocked' method, but the declaration of the
doThrowdoes. If you have a spy and don't want a method to be executed, then
doNothing` will change the behaviour.
该doNothing
方法不会改变mocked' method, but the declaration of the
doThrow does. If you have a spy and don't want a method to be executed, then
doNothing` 的行为会改变行为。
回答by Jeff Bowman
A few points, numbered just for ease of reference:
几点,编号只是为了方便参考:
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@Mock
orMockito.mock
, you can use an arbitrary Answer or any of Mockito's standardor additionalanswers.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.
doNothing
, then, gets most of its value from either overriding default behavioror setting up an action in a chain.
模拟的默认行为是每次都返回一个适当的虚拟值,通常是零
null
、 或空字符串。间谍的默认行为是调用间谍的真实实现。当然,通过@Mock
或 的参数Mockito.mock
,您可以使用任意答案或任何 Mockito 的标准或附加答案。当多个动作作为链的一部分给出时,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
,然后,通过覆盖默认行为或在链中设置操作来获取其大部分价值。
So what the test is tryingto do is to doNothing
the first time such that the verification will succeed, and then doThrow
the second time to satisfy the expected exception. Though a failed verify
would (correctly) fail the test because Mockito's errors subclass Error and not Exception, you're right that a removal of the doNothing
would 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 doNothing
in 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 */ }
}