1

对于参数类

class Criteria {
    private Map params;
    public getMap(){ return params; }
}

和一个服务方法接受这个标准

class Service{
    public List<Person> query(Criteria criteria){ ... }
}

自定义 featureMatcher 用于匹配条件键

private Matcher<Criteria> hasCriteria(final String key, final Matcher<?> valueMatcher){
    return new FeatureMatcher<Criteria, Object>((Matcher<? super Object>)valueMatcher, key, key){
        @Override protected Object featureValueOf(Criteria actual){
            return actual.getMap().get(key);
        }
    }
}

使用 mockito 验证参数时:

verify(Service).query((Criteria) argThat("id", hasCriteria("id", equalTo(new Long(12)))));

错误消息显示:

Argument(s) are different! Wanted:
Service.query(
   id <12L>
);
-> at app.TestTarget.test_id (TestTarget.java:134)
Actual invocation has different arguments:
Service.query(
   app.Criteria@509f5011
);

如果我使用ArugmentCaptor

ArgumentCaptor<Criteria> argument = ArgumentCaptor.forClass(Criteria.class);
verify(Service).query(argument.capture());
assertThat(argument.getValue(), hasCriteria("id", equalTo(new Long(12))));

消息要好得多:

Expected: id <12L> but id was <2L>

我怎样才能得到这样的消息,而不使用ArgumentCaptor

4

1 回答 1

1

简短的回答是调整Criteria代码,如果它在你的控制之下,写一个更好的toString方法。否则,您最好使用该ArgumentCaptor方法。

为什么没有 ArgumentCaptor 很难做到?你知道你期待一个电话,但 Mockito 旨在处理它,即使你有十几个类似的电话要评估。即使您使用相同的匹配器实现,具有相同的有用describeMismatch实现,assertThat本质上也会尝试一次匹配发现不匹配的位置verify并继续尝试匹配任何其他调用。

考虑一下:

// in code:
dependency.call(true, false);
dependency.call(false, true);
dependency.call(false, false);

// in test:
verify(mockDependency).call(
    argThat(is(equalTo(true))),
    argThat(is(equalTo(true))));

在这里,Mockito 不知道应该是哪个调用call(true, true);这三个中的任何一个都可能是它。相反,它只知道您期望的验证从未满足,并且三个相关调用之一可能已关闭。在带有 的代码中ArgumentCaptor,您可以使用只有一个调用的知识,并提供更合理的错误消息;对于 Mockito,它所能做的最好的事情就是输出它 DID 收到的所有调用,如果没有toString对你有用的输出Criteria,那根本不是很有帮助。

于 2013-09-03T22:34:02.677 回答