如何使用hamcrest和mockito断言超类列表等于子类匹配器

时间:2014-06-02 21:34:22

标签: java mockito hamcrest

我正在尝试执行以下操作。

final Matcher<SuperClass> matcher1 = Matchers.hasProperty("a", equalTo("b"));
final Matcher<SuperClass> matcher2 = Matchers.hasProperty("c", equalTo("d"));
final Matcher<SuperClass> matchers = Matchers.allOf(matcher1, matcher2);

List<SubClass> list = someStuff();

assertThat(list, everyItem(matchers));

我在断言行上遇到编译错误,有没有简单的方法来摆脱它。

2 个答案:

答案 0 :(得分:2)

选项1:

@SuppressWarnings({"unchecked", "rawtypes"})
@Test public void yourTest() {
    final Matcher<SuperClass> matcher1 = Matchers.hasProperty("a", equalTo("b"));
    final Matcher<SuperClass> matcher2 = Matchers.hasProperty("c", equalTo("d"));
    final Matcher<SuperClass> matchers = Matchers.allOf(matcher1, matcher2);
    List<SubClass> list = someStuff();
    // Note cast to raw type here, corresponding to the suppressed warnings.
    assertThat(list, (Matcher) everyItem(matchers));
}

选项2:

// These are all of type Matcher<SubClass> instead.
final Matcher<SubClass> matcher1 = Matchers.hasProperty("a", equalTo("b"));
final Matcher<SubClass> matcher2 = Matchers.hasProperty("c", equalTo("d"));
final Matcher<SubClass> matchers = Matchers.allOf(matcher1, matcher2);
List<SubClass> list = someStuff();
assertThat(list, everyItem(matchers));

为什么? Java的泛型处理对于Hamcrest来说太聪明了。 everyItem(matchers)会返回Matcher<Iterable<SuperClass>>,但您没有Iterable<SuperClass>,而是Iterable<SubClass>。如果你实际上你的Matcher方法产生了Matcher<Iterable<? extends SuperClass>>,那一切都会好的,但是你几乎不可能让Java相信你的matcher1matcher2是相互兼容的。

答案 1 :(得分:0)

泛型。

您的代码的问题在于您尝试断言类型为List<SubClass>的列表与匹配Matcher<SuperClass>的匹配器的每个项目匹配。

即使SuperClass扩展SubClassassertThat方法也要求两者相同。

因此,如果您强制使用someStuff()方法返回SuperClass的列表,那么您应该免费回家。即像这样的东西

    List<SuperClass> list = someStuff();
    assertThat(list, everyItem(matchers));

将摆脱编译错误。