Assert集合包含自定义类的对象,它不会覆盖equals / hashcode

时间:2015-09-21 15:00:54

标签: java collections junit equals hamcrest

我们有一个包含多个字段的自定义类,我们无法为业务域原因覆盖equals / hashcode方法

然而,在单元测试期间,我们应断言集合是否包含此类的项目

List<CustomClass> customObjectList = classUnderTest.methodUnderTest();
//create customObject with fields set to the very same values as one of the elements in customObjectList
//we should assert here that customObjectList contains customObject

但是,到目前为止,我们没有找到任何可以在不覆盖equals / hashcode的情况下工作的解决方案,例如Hamcrest

assertThat(customObjectList, contains(customObject));

导致AssertionError引用

Expected: iterable containing [<CustomClass@578486a3>]
but: item 0: was <CustomClass@551aa95a>

是否有解决方案而无需逐场比较?

5 个答案:

答案 0 :(得分:4)

如果您使用的是Java8,则可以使用Stream#anyMatch和您自己的customEquals方法。像这样的东西会起作用 -

   assertTrue(customObjectList.stream()
                 .anyMatch(object -> customEquals(object,customObject)));

更新以反映Holger的评论

答案 1 :(得分:1)

Fest Assertions具有以下内容:

assertThat(expected).isEqualsToByComparingFields(actual);

我认为它在引擎盖下进行了反思比较。我们遇到了类似的问题,这使我们免于编写自定义比较逻辑。

另一件事是扩展您选择的断言框架,以适合您的确切类和案例。这种方法应该减少使用深度反射比较的一些性能开销。

答案 2 :(得分:1)

assertj擅长这一点。尤其是custom comparison strategy

private static class CustomClass {
    private final String string;

    CustomClass(String string) {
        this.string = string;
    }

    // no equals, no hashCode!
}

@Test
public void assertjToTheRescue() {
    List<CustomClass> list = Arrays.asList(new CustomClass("abc"));

    assertThat(list).usingFieldByFieldElementComparator().contains(new CustomClass("abc"));
}

assertj提供了许多其他usingComparator方法。

答案 3 :(得分:0)

没有

Collection接口的许多方法都是根据equals()明确定义的。例如。 Collection#contains()

  

如果此集合包含指定的元素,则返回true。更多   正式地,当且仅当此集合包含at时返回true   至少一个元素e(o==null ? e==null : o.equals(e))

只为每个按字段收集和比较字段。您可以将比较/等于逻辑存储到静态实用程序类中,如CustomClasses或类似,然后编写自定义Hamcrest匹配器。

或者,使用反射等于,例如来自Apache Commons LangHamcrest extension或(最好)迁移到AssertJhas this functionality out of the box

assertThat(ImmutableList.of(frodo))
        .usingFieldByFieldElementComparator()
        .contains(frodoClone);

这是一个黑客和狡猾,但足够的测试。请不要在生产代码中使用。

答案 4 :(得分:0)

我知道使用Hamcrest的两个解决方案。第一个测试项目的一些属性。

assertThat(customObjectList, contains(allOf(
    hasProperty("propertyA", equalTo("someValue")),
    hasProperty("propertyB", equalTo("anotherValue")))));

或者您可以使用Nitor Creations中的reflectEquals匹配器:

assertThat(customObjectList, contains(reflectEquals(customObject)));