具有不同对象的自定义匹配器
Custom matchers with different object
您好,我正在编写自定义匹配器来验证两个不同的对象,我的代码是:
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,它允许传递不同的对象来简单地依赖于匹配的输出,而不是强制相同的实际和预期类型?
注意将 Mockito 匹配器和 Hamcrest 匹配器分开。 Hamcrest 或 Hamcrest 风格的匹配器是一个对象实例,就像上面的 new DetailsMatcher(expected)
一样。通过调用 argThat
,您的 valueObjectEq
似乎 return 一个 Details
对象,但事实并非如此:它将 return null
和 Mockito将在内部堆栈上保存一个对象。因此,你不应该在调用 when
或 verify
.
之外调用 argThat
相反,将您的 DetailsMatcher 更改为 ArgumentMatcher<Request>
类型,以表明您的 Matcher 可以在任何 Request
上工作,而不仅仅是 Details
,并使构造函数 public 所以你可以这样称呼它:
assertThat(requestModel, new DetailsMatcher(orderResponse));
// or with a static helper method you write:
assertThat(requestModel, matchesValueObject(orderResponse));
其他一些注意事项:
Matcher.matches
永远不应抛出异常,但如果您传入非请求,它会在此处抛出异常。如果参数不是匹配器,请检查 instanceof
和 return false
。
- Mockito 2.0 使 ArgumentMatcher 成为自己的 class,而不是扩展
org.hamcrest.Matcher
。如果你想继续使用 Matcher 的 Hamcrest 属性,你可能需要让它扩展两者,或者只是让它成为 Hamcrest 匹配器并调整 valueObjectEq
以调用 MockitoHamcrest.argThat。
虽然错误信息不会那么清楚,但您始终可以手动调用该方法:
assertTrue(new DetailsMatcher(orderReponse).matches(requestModel));
另请参阅:
- Mockito's Matcher vs Hamcrest Matcher?
- How do Mockito matchers work?
您好,我正在编写自定义匹配器来验证两个不同的对象,我的代码是:
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,它允许传递不同的对象来简单地依赖于匹配的输出,而不是强制相同的实际和预期类型?
注意将 Mockito 匹配器和 Hamcrest 匹配器分开。 Hamcrest 或 Hamcrest 风格的匹配器是一个对象实例,就像上面的 new DetailsMatcher(expected)
一样。通过调用 argThat
,您的 valueObjectEq
似乎 return 一个 Details
对象,但事实并非如此:它将 return null
和 Mockito将在内部堆栈上保存一个对象。因此,你不应该在调用 when
或 verify
.
argThat
相反,将您的 DetailsMatcher 更改为 ArgumentMatcher<Request>
类型,以表明您的 Matcher 可以在任何 Request
上工作,而不仅仅是 Details
,并使构造函数 public 所以你可以这样称呼它:
assertThat(requestModel, new DetailsMatcher(orderResponse));
// or with a static helper method you write:
assertThat(requestModel, matchesValueObject(orderResponse));
其他一些注意事项:
Matcher.matches
永远不应抛出异常,但如果您传入非请求,它会在此处抛出异常。如果参数不是匹配器,请检查instanceof
和 returnfalse
。- Mockito 2.0 使 ArgumentMatcher 成为自己的 class,而不是扩展
org.hamcrest.Matcher
。如果你想继续使用 Matcher 的 Hamcrest 属性,你可能需要让它扩展两者,或者只是让它成为 Hamcrest 匹配器并调整valueObjectEq
以调用 MockitoHamcrest.argThat。 虽然错误信息不会那么清楚,但您始终可以手动调用该方法:
assertTrue(new DetailsMatcher(orderReponse).matches(requestModel));
另请参阅:
- Mockito's Matcher vs Hamcrest Matcher?
- How do Mockito matchers work?