使用Hamcrest映射平等

mo-*_*eph 48 java collections hamcrest

我想使用hamcrest声明两个映射相等,即它们具有指向相同值的相同键集.

我目前最好的猜测是:

assertThat( affA.entrySet(), hasItems( affB.entrySet() );
Run Code Online (Sandbox Code Playgroud)

这使:

方法断言Assert类型中的(T,Matcher)不适用于参数(Set>,Matcher >>>)

我还研究了containsAll的变体,以及hamcrest包提供的其他一些变体.谁能指出我正确的方向?或者我是否必须编写自定义匹配器?

Han*_*örr 53

我提出的最短路径是两个陈述:

assertThat( affA.entrySet(), everyItem(isIn(affB.entrySet())));
assertThat( affB.entrySet(), everyItem(isIn(affA.entrySet())));
Run Code Online (Sandbox Code Playgroud)

但你也可以这样做:

assertThat(affA.entrySet(), equalTo(affB.entrySet()));
Run Code Online (Sandbox Code Playgroud)

取决于地图的实现.

更新:实际上有一个语句独立于集合类型工作:

assertThat(affA.entrySet(), both(everyItem(isIn(affB.entrySet()))).and(containsInAnyOrder(affB.entrySet())));
Run Code Online (Sandbox Code Playgroud)

  • @Taras:报告对`.equals()`的帮助不大 (9认同)
  • 我不得不将对affB的第二次访问转换为一个数组:`.and(containsInAnyOrder(affB.entrySet()。toArray())` (3认同)

Ale*_*rev 38

有时候Map.equals()就足够了.但有时您不知道Map测试下的代码会返回s 的类型,因此您不知道是否.equals()能正确地将代码返回的未知类型的地图与您构建的地图进行比较.或者您不希望将代码与此类测试绑定.

另外,单独构建地图以比较结果是恕我直言不是很优雅:

Map<MyKey, MyValue> actual = methodUnderTest();

Map<MyKey, MyValue> expected = new HashMap<MyKey, MyValue>();
expected.put(new MyKey(1), new MyValue(10));
expected.put(new MyKey(2), new MyValue(20));
expected.put(new MyKey(3), new MyValue(30));
assertThat(actual, equalTo(expected));
Run Code Online (Sandbox Code Playgroud)

我更喜欢使用machers:

import static org.hamcrest.Matchers.hasEntry;

Map<MyKey, MyValue> actual = methodUnderTest();
assertThat(actual, allOf(
                      hasSize(3), // make sure there are no extra key/value pairs in map
                      hasEntry(new MyKey(1), new MyValue(10)),
                      hasEntry(new MyKey(2), new MyValue(20)),
                      hasEntry(new MyKey(3), new MyValue(30))
));
Run Code Online (Sandbox Code Playgroud)

我必须定义hasSize()自己:

public static <K, V> Matcher<Map<K, V>> hasSize(final int size) {
    return new TypeSafeMatcher<Map<K, V>>() {
        @Override
        public boolean matchesSafely(Map<K, V> kvMap) {
            return kvMap.size() == size;
        }

        @Override
        public void describeTo(Description description) {
            description.appendText(" has ").appendValue(size).appendText(" key/value pairs");
        }
    };
}
Run Code Online (Sandbox Code Playgroud)

还有另一种变体hasEntry(),它将匹配器作为参数而不是键和值的精确值.如果您需要除了每个键和值的相等测试之外的其他内容,这可能很有用.

  • 你应该使用`org.hamcrest.collection.IsMapWithSize.aMapWithSize(Matcher <?super Integer>)而不是你自己的`hasSize`方法. (6认同)