问题 Hamcrest等于收藏


Hamcrest中是否有匹配器来比较集合的平等性? 有 contains 和 containsInAnyOrder 但是我需要 equals 不受具体集合类型的约束。 例如。我无法将Arrays.asList和Map.values与Hamcrest进行比较 equals

提前致谢!


9283
2017-12-25 10:53


起源

也可以看看 stackoverflow.com/q/2509293/21499 - Hans-Peter Störr
Arrays.asList().equals(new HashMap<>().values()) == false  Lists和 Sets永远不会彼此相等。 - Arend v. Reinersdorff


答案:


我无法比较Arrays.asList和   具有Hamcrest的Map.values等于。

这是因为hamcrest的过热型签名。您 能够 做这个相等比较,但你需要施放 List 反对 Collection 在它编译之前。

我经常不得不使用Hamcrest进行投射,这感觉不对,但这是有时候进行编译的唯一方法。


7
2017-12-25 11:32





转换为集合可能有效,但它对底层Collection实现做了一些假设(例如,订单?)。更通用的方法是编写自己的匹配器。

这是一个几乎完整的匹配器实现,可以执行您想要的操作(您需要填写导入和describeTo方法)。请注意,此实现要求两个集合的所有元素相等,但不一定按相同的顺序排列。

public class IsCollectionOf<T> extends TypeSafeMatcher<Collection<T>> {
    private final Collection<T> expected;
    public IsCollectionOf(Collection<T> expected) {
        this.expected = expected;
    }
    public boolean matchesSafely(Collection<T> given) {
        List<T> tmp = new ArrayList<T>(expected);
        for (T t : given) {
            if (!tmp.remove(t)) {
                return false;
            }
        return tmp.isEmpty();
    }
    // describeTo here
    public static <T> Matcher<Collection<T>> ofItems(T... items) {
        return new IsCollectionOf<T>(Arrays.asList(items));
    }
}

4
2018-01-08 13:41





如果您在集合实现的equals方法上遇到问题,您也可以先复制集合:

assertThat( new ArrayList<Whatever>(actual), equalTo( new ArrayList<Whatever>(expected) );

以下可能也有效:

assertThat(actual, both(everyItem(isIn(expected))).and(containsInAnyOrder(expected)));

1
2017-08-27 15:54