如何让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.doThrowMockito.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文档 。