如何让Mockito模拟按顺序执行不同的操作?
以下代码:
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"); }
预期的产出是
例外
对?
但我一无所获
如果我在doNothing之后做了doThrow我得到了
例外
例外
所以它看起来像是最后一个被嘲笑的模拟……我认为它会按照它们注册的顺序进行模拟吗?
我想制作一个模拟第一次抛出exception,第二次正常完成…
Mockito可以使用相同的参数来连续行为 – 永远重复最终指令 – 但它们都必须是同一“链”的一部分。 否则,Mockito会有效地认为你已经改变了主意并覆盖了之前被嘲弄的行为,如果你在setUp
或@Before
方法中建立了良好的默认值并希望在特定的测试用例中覆盖它们,这不是一个糟糕的特性。
“Mockito动作将在下一次发生”的一般规则:将选择与所有参数匹配的最近定义的链 。 在链中,每个动作将发生一次(如果像thenReturn(1, 2, 3)
那样计算多个则thenReturn
值),然后最后一个动作将永远重复。
// doVerb syntax, for void methods and some spies Mockito.doThrow(new IOException()) .doNothing() .when(mapper).writeValue( (OutputStream) Matchers.anyObject(), Matchers.anyObject());
这相当于更常见的when
语法中的chained thenVerb
语句,您在这里为void
方法正确地避免了:
// when/thenVerb syntax, to mock methods with return values when(mapper.writeValue( (OutputStream) Matchers.anyObject(), Matchers.anyObject()) .thenThrow(new IOException()) .thenReturn(someValue);
请注意,您可以对Mockito.doThrow
和Mockito.doThrow
Matchers.*
使用静态导入,并切换到any(OutputStream.class)
而不是(OutputStream) anyObject()
,并结束:
// doVerb syntax with static imports doThrow(new IOException()) .doNothing() .when(mapper).writeValue(any(OutputStream.class), anyObject());
有关可链接的完整命令列表,请参阅Mockito的Stubber文档 。