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

Mic*_*les 8 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");
  }
Run Code Online (Sandbox Code Playgroud)

预期的产出是

例外

对?

但我一无所获

如果我在doNothing之后做了doThrow我得到了

例外情况
除外

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

我想制作一个模拟第一次抛出异常,第二次正常完成...

Jef*_*ica 16

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());
Run Code Online (Sandbox Code Playgroud)

这相当于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);
Run Code Online (Sandbox Code Playgroud)

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

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

有关可以链接的完整命令列表,请参阅Mockito的Stubber文档.