使用Hamcrest地图平等
我想用hamcrest来声明两个地图是平等的,也就是说,它们有相同的一组键指向相同的值。
我目前最好的猜测是:
assertThat( affA.entrySet(), hasItems( affB.entrySet() );
这使:
Asserttypes中的assertThat(T,Matcher)不适用于参数(Set>,Matcher >>>)
我也研究了containsAll的变体,还有一些由hamcrest包提供的变体。 任何人都可以指向正确的方向吗? 还是我必须写一个自定义的匹配器?
我提出的最短路线是两条语句:
assertThat( affA.entrySet(), everyItem(isIn(affB.entrySet()))); assertThat( affB.entrySet(), everyItem(isIn(affA.entrySet())));
但你也可以做:
assertThat(affA.entrySet(), equalTo(affB.entrySet()));
取决于地图的实现。
更新:实际上有一个独立于集合types的语句:
assertThat(affA.entrySet, both(everyItem(isIn(affB.entrySet()))).and(containsInAnyOrder(affB.entrySet())));
有时Map.equals()
就够了。 但有时你不知道在testing下代码返回的Map
types,所以你不知道.equals()
是否会正确地比较由你构造的地图代码返回的未知types的地图。 或者你不想用这样的testing来绑定你的代码。
此外,分别构build一个地图来比较结果是恕我直言,不是很优雅:
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));
我更喜欢使用马歇尔:
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)) ));
我必须自己定义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"); } }; }
还有hasEntry()
另一个变体,它将匹配器作为参数,而不是键和值的确切值。 如果您需要除每个键和值的平等testing之外的其他内容,这可能会很有用。
我喜欢使用番石榴ImmutableMap 。 他们支持Map.equals()
并且很容易构造。 唯一的技巧是明确指定types参数,因为hamcrest将假定ImmutableMap
types。
assertThat( actualValue, Matchers.<Map<String, String>>equalTo( ImmutableMap.of( "key1", "value", "key2", "other-value" ) ) );
现在可用的另一种select是使用Hamcrest的Cirneco扩展 。 它有hasSameKeySet()
(以及Guava“collections”的其他匹配器)。 根据你的例子,这将是:
assertThat(affA, hasSameKeySet(affB));
您可以对基于JDK7的项目使用以下依赖项:
<dependency> <groupId>it.ozimov</groupId> <artifactId>java7-hamcrest-matchers</artifactId> <version>0.7.0</version> </dependency>
或者如果您使用的是JDK8或更高版本,请使用以下命令:
<dependency> <groupId>it.ozimov</groupId> <artifactId>java8-hamcrest-matchers</artifactId> <version>0.7.0</version> </dependency>
Hamcrest现在有一个Matcher
的大小收集。
org.hamcrest.collection.IsCollectionWithSize
这就像一个魅力,并不需要像接受的答案一样的两个断言。
assertThat( actualData.entrySet().toArray(), arrayContainingInAnyOrder(expectedData.entrySet().toArray()) );
如果您需要将一组结果与预期进行比较,并且您select使用assertj库,则可以这样做:
// put set of expected values by your test keys Map<K, V> expectations = ...; // for each test key get result Map<K, V> results = expectations.keySet().stream().collect(toMap(k -> k, k -> getYourProductionResult(k))); assertThat(results).containsAllEntriesOf(expectations);
请注意, containsAllEntriesOf
不会比较地图的相等性。 如果您的产品代码实际返回一个Map<K, V>
您可能需要添加一个检查关键字assertThat(results).containsOnlyKeys((K[]) expectations.keySet().toArray());