Java 如何让 Mockito 模拟按顺序执行不同的操作?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/20098607/
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
How can I make a Mockito mock perform different actions in sequence?
提问by Michael Wiles
The following code:
以下代码:
ObjectMapper mapper = Mockito.mock(ObjectMapper.class);
Mockito.doThrow(new IOException()).when(mapper).writeValue((OutputStream) Matchers.anyObject(), Matchers.anyObject());
Mockito.doNothing().when(mapper).writeValue((OutputStream) Matchers.anyObject(), Matchers.anyObject());
try {
mapper.writeValue(new ByteArrayOutputStream(), new Object());
} catch (Exception e) {
System.out.println("EXCEPTION");
}
try {
mapper.writeValue(new ByteArrayOutputStream(), new Object());
} catch (Exception e) {
System.out.println("EXCEPTION");
}
The expected output is
预期的输出是
EXCEPTION
例外
right?
对?
But I get nothing
但我一无所获
If I then make the doThrow after the doNothing I get
如果我在 doNothing 之后做 doThrow 我得到
EXCEPTION
EXCEPTION
例外
例外
So It looks like it is the last mock that is the one that is taken... I thought it would take the mocks in the order they're registered?
所以看起来它是最后一个被采用的模拟......我认为它会按照它们注册的顺序进行模拟?
I'm looking to produce a mock throws the exception first time and completes normally the second time...
我正在寻找一个模拟,第一次抛出异常并第二次正常完成......
采纳答案by Jeff Bowman
Mockito can stub consecutive behavior with the same parameters—forever repeating the final instruction—but they all have to be part of the same "chain". Otherwise Mockito effectively thinks you've changed your mind and overwrites your previously-mocked behavior, which isn't a bad feature if you've established good defaults in a setUp
or @Before
method and want to override them in a specific test case.
Mockito 可以用相同的参数存根连续的行为——永远重复最后的指令——但它们都必须是同一个“链”的一部分。否则 Mockito 会有效地认为您改变了主意并覆盖了您之前被嘲笑的行为,如果您在 a setUp
or@Before
方法中建立了良好的默认值并希望在特定测试用例中覆盖它们,这不是一个坏功能。
The general rules for "which Mockito action will happen next":The most-recently-defined chainthat matches all arguments will be selected. Within the chain, each action will happen once (counting multiple thenReturn
values if given like thenReturn(1, 2, 3)
), and then the last action will be repeated forever.
对于“该行动的Mockito接下来将发生”的一般规则:在近期被定义的最链,所有的参数匹配将被选中。在链中,每个动作都会发生一次(thenReturn
如果给定像thenReturn(1, 2, 3)
,则计算多个值),然后最后一个动作将永远重复。
// doVerb syntax, for void methods and some spies
Mockito.doThrow(new IOException())
.doNothing()
.when(mapper).writeValue(
(OutputStream) Matchers.anyObject(), Matchers.anyObject());
This is the equivalent of chained thenVerb
statements in the more-common when
syntax, which you correctly avoided here for your void
method:
这相当于thenVerb
更常见when
语法中的链式语句,您在此处正确避免了您的void
方法:
// when/thenVerb syntax, to mock methods with return values
when(mapper.writeValue(
(OutputStream) Matchers.anyObject(), Matchers.anyObject())
.thenThrow(new IOException())
.thenReturn(someValue);
Note that you can use static imports for Mockito.doThrow
and Matchers.*
, and switch to any(OutputStream.class)
instead of (OutputStream) anyObject()
, and wind up with this:
请注意,您可以对Mockito.doThrow
and使用静态导入Matchers.*
,然后切换到any(OutputStream.class)
而不是(OutputStream) anyObject()
,最后得到以下结果:
// doVerb syntax with static imports
doThrow(new IOException())
.doNothing()
.when(mapper).writeValue(any(OutputStream.class), anyObject());
See Mockito's documentation for Stubberfor a full list of commands you can chain.
有关可以链接的完整命令列表,请参阅Mockito 的 Stubber 文档。