您好我正在编写自定义匹配器来验证两个不同的对象,我的代码是:
public class DetailsMatcher extends ArgumentMatcher <Details> {
private final Details expected;
private DetailsMatcher(Details expected) {
this.expected = expected;
}
@Override
public boolean matches(Object actual) {
return ((Request) actual).getId().equals(expected.getId());
}
@Override
public void describeTo(Description description) {
description.appendText(expected == null ? null : expected.toString());
}
public static Details valueObjectEq(Details expected) {
return argThat(new DetailsMatcher(expected));
}
}
我想在我的测试中使用它:
assertThat(requestModel, DetailsMatcher.valueObjectEq(response));
但这些是两个不同的对象,所以它不起作用。我不想仅仅为了测试目的而改变我的对象,所以我们有一些类似于assertThat的api,它允许传递不同的对象简单地依赖于匹配的输出,而不是强制实际和期望的相同类型?
答案 0 :(得分:1)
小心将Mockito匹配器和Hamcrest匹配器分开。 Hamcrest或Hamcrest风格的匹配器是一个对象实例,就像上面的new DetailsMatcher(expected)
一样。通过拨打argThat
,您的valueObjectEq
似乎会返回Details
个对象,但事实并非如此:它将返回null
,而Mockito会保存一个对象在内部堆栈上。因此,您不应在致电argThat
或when
之外致电verify
。
相反,将您的DetailsMatcher更改为ArgumentMatcher<Request>
类型,以表明您的匹配器可以处理任何Request
,而不只是Details
,并将构造函数设为公共,以便您可以调用它像这样:
assertThat(requestModel, new DetailsMatcher(orderResponse));
// or with a static helper method you write:
assertThat(requestModel, matchesValueObject(orderResponse));
其他几点说明:
Matcher.matches
应该永远不会抛出异常,但如果您传入非请求,它将在此处执行此操作。如果参数不是匹配器,请查看instanceof
并返回false
。org.hamcrest.Matcher
。如果你想继续使用Matcher来获得它的Hamcrest属性,你可能需要将它扩展为两者,或者只是将它作为Hamcrest匹配器并调整valueObjectEq
来调用MockitoHamcrest.arg而不是。虽然错误消息不会很清楚,但您始终可以手动调用该方法:
assertTrue(new DetailsMatcher(orderReponse).matches(requestModel));
另见: