如何让Mockito模拟按顺序执行不同的操作?

时间:2013-11-20 14:29:24

标签: java 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

  

异常
  例外

所以它看起来像是最后一个被嘲笑的模拟......我认为它会按照他们注册的顺序进行模拟吗?

我正在制作一个模拟第一次抛出异常并且第二次正常完成......

1 个答案:

答案 0 :(得分:15)

Mockito可以使用相同的参数来连续行为 - 永远重复最终指令 - 但它们都必须属于同一个“链”。否则,Mockito会有效地认为你已经改变了主意并覆盖了之前被嘲弄的行为,如果你已经在setUp@Before方法中建立了良好的默认值并且想要覆盖,那么这不是一个糟糕的功能他们在一个特定的测试案例中。

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

这相当于更常见的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);

请注意,您可以对Mockito.doThrowMatchers.*使用静态导入,并切换到any(OutputStream.class)而不是(OutputStream) anyObject(),最后结束:

// doVerb syntax with static imports
doThrow(new IOException())
    .doNothing()
    .when(mapper).writeValue(any(OutputStream.class), anyObject());

有关可以链接的完整命令列表,请参阅Mockito's documentation for Stubber