如何使用不同的参数验证多个方法调用

时间:2011-12-14 11:57:52

标签: java mockito

我有以下方法可以验证

上的行为
public void methodToTest( Exception e, ActionErrors errors ) {

    ...
        errors.add( "exception.message", 
                    ActionMessageFactory.createErrorMessage(e.toString() ));

        errors.add( "exception.detail",
                    ActionMessageFactory.createErrorMessage(e.getStackTrace()[0].toString() ));

    ...
}

在我的@Test课程中,我希望做这样的事情来验证errors.add()是用“exception.message”调用的,还是用“exception.detail”调用

verify(errors).add(eq("exception.message"), any(ActionError.class));
verify(errors).add(eq("exception.detail"), any(ActionError.class));
然而,Mockito抱怨​​如下

Argument(s) are different! Wanted:
actionErrors.add(
    "exception.message",
    <any>
);

Actual invocation has different arguments:
actionErrors.add(
    "exception.detail",
    org.apache.struts.action.ActionError@38063806
);

我如何告诉Mockito检查这两个值?

7 个答案:

答案 0 :(得分:88)

进一步阅读使我尝试使用ArgumentCaptors和以下作品,虽然比我想要的更冗长。

ArgumentCaptor<String> argument = ArgumentCaptor.forClass(String.class);

verify(errors, atLeastOnce()).add(argument.capture(), any(ActionMessage.class));

List<String> values = argument.getAllValues();

assertTrue(values.contains("exception.message"));
assertTrue(values.contains("exception.detail"));

答案 1 :(得分:48)

如果两个add()来电的顺序相关,您可以使用InOrder

InOrder inOrder = inOrder(errors, errors);
inOrder.verify(errors).add(eq("exception.message"), any(ActionError.class));
inOrder.verify(errors).add(eq("exception.detail"), any(ActionError.class));

答案 2 :(得分:22)

尝试这样的事情:

verify(errors, times(2))
     .add(AdditionalMatchers.or(eq("exception.message"), eq("exception.detail")),
          any(ActionError.class));

答案 3 :(得分:16)

您的代码可能存在问题。因为事实上你实际上是在编写这段代码:

Map<Character, String> map = mock(Map.class);

map.put('a', "a");
map.put('b', "b");
map.put('c', "c");

verify(map).put(eq('c'), anyString());
verify(map).put(eq('a'), anyString());
verify(map).put(eq('b'), anyString());

请注意,就实际调用而言,第一次验证的顺序并不合适。

另外,我建议你实际上不要模拟你不拥有的类型,例如struts类型。

[编辑@Brad]

在我的IDE中运行Brice的代码(上面)后,我可以看到我使用了ActionError而不是ActionMessage,所以这就是我的verify()不匹配的原因。我最初发布的错误消息误导我认为这是第一个不匹配的参数。事实证明这是第二个论点。

所以我的问题的答案是

/** 
 * note that ActionMessageFactory.createErrorMessage() returns ActionMessage
 * and ActionError extends ActionMessage
 */
verify(errors).add(eq("exception.message"), any(ActionMessage.class));
verify(errors).add(eq("exception.detail"), any(ActionMessage.class));

答案 4 :(得分:7)

你可以使用允许Mockito传递测试的Mockito.atLeastOnce(),即使多次调用mockObject也是如此。

Mockito.verify(mockObject, Mockito.atLeastOnce()).testMethod(Mockito.eq(1));

Mockito.verify(mockObject, Mockito.atLeastOnce()).testMethod(Mockito.eq(2));

答案 5 :(得分:3)

1)告诉Mokito通话总期望值。

2)告诉Mokito,每个参数组合期望多少次。

verify(errors, times(2)).add(any(), any(ActionMessage.class));

verify(errors, atLeastOnce()).add(eq("exception.message"), any());
verify(errors, atLeastOnce()).add(eq("exception.detail"), any());

答案 6 :(得分:0)

以类似于@ sendon1928的方式,我们可以使用:

Mockito.times(wantedInvocationCount)

确保方法被调用的确切次数(我认为最好的解决方案)。之后,我们可以致电

Mockito.verifyNoMoreInteractions(mock)

确保在任何情况下都不再使用模拟程序。完整示例:

Mockito.verify(mockObject, Mockito.times(wantedInvocationCount)).testMethod(Mockito.eq(1));

Mockito.verify(mockObject, Mockito.times(wantedInvocationCount)).testMethod(Mockito.eq(2));

Mockito.verifyNoMoreInteractions(mockObject)