如何使用Mockito测试对同一方法的两个不同调用,为每个调用返回不同的响应?

时间:2016-07-15 22:35:13

标签: java mockito

使用Mockito,我需要测试一个在同一个事务中被调用两次的方法,并且每次都返回不同的值。

我有两个测试 - 每个电话一个。

第一个是:

verify(mockAppender, times(2)).doAppend(logEventArgumentCaptor.capture());

assertThat(logEventArgumentCaptor.getValue().getMessage(), containsString("Error response: " + RESPONSE ));

虽然第二次读到:

verify(mockAppender, times(2)).doAppend(logEventArgumentCaptor.capture());

assertThat(logEventArgumentCaptor.getValue().getMessage(), containsString("Request body: " + BODY));

正在测试的代码为:

if (!statusCode.is2xxSuccessful()) {
  LOG.error("Error response: "+response);
  LOG.error("Request body: "+bodyString);
}

第二次测试通过,因为它找到了第二个响应,但是第一个测试失败了,因为它也找到了第二个响应。如何才能让第一个测试只查看方法的第一个响应?或者是否有一种断言形式可以让我立刻检查两个响应?

1 个答案:

答案 0 :(得分:0)

ArgumentCaptor支持getAllValues()调用,该调用返回每个匹配捕获的列表。您可以使用它来验证这两个消息。

verify(mockAppender, times(2)).doAppend(logEventArgumentCaptor.capture());

assertThat(logEventArgumentCaptor.getAllValues().get(0).getMessage(),
    containsString("Error response: " + RESPONSE ));
assertThat(logEventArgumentCaptor.getAllValues().get(1).getMessage(),
    containsString("Request body: " + BODY));

但是,在一般情况下,这是编写Hamcrest(风格)匹配器的绝佳机会,可以为您检查消息。我在这里使用了Mockito's ArgumentMatcher class,它在Mockito 1.x中扩展了Hamcrest的Matcher,但在Mockito 2.0中打破了这种依赖。

public class LogEventContaining implements ArgumentMatcher<LogEvent> {
  private final String searchText;

  public LogEventContaining(String searchText) {
    this.searchText = searchText;
  }

  @Override public boolean matches(LogEvent logEvent) {
    // You could also use your Hamcrest matcher here.
    return logEvent.getMessage().indexOf(searchText) >= 0;
  }

  @Override public String toString() {
    return String.format("log message containing '%s'", searchText);
  }
}

// Per Mockito/Hamcrest style. This could go anywhere.
public static ArgumentMatcher<LogEvent> isALogEventContaining(String searchText) {
  return new LogEventContaining(searchText);
}

现在,您可以在whenverify调用中使用它,包含适配器argThat

verify(mockAppender)
    .doAppend(argThat(isALogEventContaining("Error response: " + RESPONSE)));
verify(mockAppender, never())
    .doAppend(argThat(isALogEventContaining("Request body: " + BODY)));
when(mockAppender.doAppend(argThat(isALogEventContaining("Foo"))))
    .thenThrow(new RuntimeException("Log not available"));

有关使用argThat以及您需要的原因的更多信息,请参阅:How do Mockito matchers work?