mockito验证的测试失败消息



对于参数类

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

并且服务方法接受这个标准

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

自定义功能匹配器用于匹配标准密钥

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,我如何获得这样的消息?

简单的答案是调整Criteria代码,如果它在您的控制之下,则编写更好的toString方法。否则,您最好使用ArgumentCaptor方法。

为什么没有ArgumentCaptor很难你知道你期待着一个电话,但Mockito的设计是为了处理它,即使你有十几个类似的电话要评估。即使您使用相同的matcher实现,使用相同的有用的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,那就一点帮助都没有。

相关内容

  • 没有找到相关文章

最新更新