Mockito使用匹配器Mock(Object.class)& anyString()

时间:2016-12-06 10:15:37

标签: java junit mockito matcher hamcrest

奥拉,

我正在忙于编写像

这样的单元测试
 monitor.severe(mock(MonitorEventType.class), anyString());

当我执行此操作时,我得到:

 Invalid use of argument matchers.
 0 matchers expected, 1 recorded.

所以我试过了:

monitor.severe(mock(MonitorEventType.class), eq(anyString()));

但是这给了

Invalid use of argument matchers.
0 matchers expected, 2 recorded.

我也尝试使用

monitor.severe(any(MonitorEventType.class), anyString());

但是这会给出一个空指针。

什么有效

   monitor.severe(mock(MonitorEventType.class), "");

但那不是我想要的。

我的testMethod是:

@Test
public void testSevere() {
    monitor.severe(mock(MonitorEventType.class), eq(anyString()));
    ArgumentCaptor<DefaultMonitoringEventImpl> captor = ArgumentCaptor.forClass(DefaultMonitoringEventImpl.class);
    verify(event).fire(captor.capture());
    DefaultMonitoringEventImpl input = captor.getValue();
    assertThat(fetchMonitorLevel(input), equalTo(MonitorEventLevel.SEVERE.getDescription()));
}

private String fetchMonitorLevel(DefaultMonitoringEventImpl input) {
    Map<String, String> map = input.getMonitorEventWaardes().getWaardenLijst();
    return map.get(MonitorEvent.MONITOR_EVENT_LEVEL_KEY);
}

测试方法是:

public void severe(MonitorEventType type, String message) {
    write(type, MonitorEventLevel.SEVERE, message, null);
}

@Asynchronous
public void write(MonitorEventType type, MonitorEventLevel level, String message, MonitorEventWaardes pEventWaardes) {
    event.fire(new DefaultMonitoringEventImpl(type, level, message, pEventWaardes));
}

我想要的是当我使用随机的MonitorEventType和随机字符串调用monitor.severe时,&#34; level&#34;参数在teh event.fire中填充了正确的值。

1 个答案:

答案 0 :(得分:2)

首先,一些基础知识:

  • mock 是真实对象的替代品,您可以使用模拟框架创建。它记录了它的交互并验证它们以供日后使用。
  • anyanyStringeq这样的匹配器会告诉您的模拟框架(不是您的测试框架或您测试的系统)什么样的调用与 stubbing 相关(告诉你的mock在调用方法时如何表现)或验证(询问你的模拟框架是否调用某个方法)。

最重要的是,JUnit和Mockito不允许使用&#34;对任何输入进行测试&#34;:any之类的语句只存在,所以当我收到任何参数时你可以说&#34; ,采取这个行动&#34;或者&#34;检查是否使用任何参数调用方法&#34;。

现在你的例子:

/* BAD */ monitor.severe(mock(MonitorEventType.class), anyString());

这不起作用,因为monitor是真实的,因此anyString不合适。不过,你的模拟很好,因为你提供了一个模拟实现来测试一个真正的实现。

/* BAD */ monitor.severe(mock(MonitorEventType.class), eq(anyString()));

这与上面的问题相同,但是加倍:eq应该采用真正的价值,而不是像anyString这样的匹配器。

/* BAD */ monitor.severe(any(MonitorEventType.class), anyString());

在这里,您已经为真正的方法调用提供了两个匹配器。匹配器只是Mockito的信号,真正的实现正在处理这个,而不是Mockito。

/*  OK */ monitor.severe(mock(MonitorEventType.class), "");

您正在为您的真实系统提供模拟实现和真实字符串,因此这是对Mockito的正确使用,即使它没有表达您想要测试的内容。 / p>

除了使用Mockito之外,这里真正的问题是你想在你的测试中引入 randomness 。即使Mockito是工作的正确工具 - 它绝对不是 - 然后你的测试可能会在90%的时间内通过,并且在10%的时间内失败,具体取决于选择的输入。这将使您的测试充其量嘈杂/片状,甚至可能导致您的团队忽略测试的价值。

相反,选择代表用例或边缘情况;如果您有一个枚举类型参数,您还可以迭代所有值并按值运行一次测试。你可能不需要Mockito,除非你出于某种原因不能轻易创建一个MonitorEventType实例;那么你可以使用Mockito创建一个假的MonitorEventType来与你正在测试的真实Monitor进行交互。