我想检查一个地图是否包含一组特定的条目。它可以包含其他不在expectedMap
中的条目。我目前有以下断言:
assertThat(expectedMap.entrySet(), everyItem(isIn(actualMap.entrySet())));
虽然这个方法可以正常工作,但是它打印的错误信息可能会让人困惑,因为预期的和接收到的参数与正常用法相反。有没有更好的方法来书写它?
hasItems
可以完成你想要的功能,但是实现方式并不明显。由于Hamcrest对匹配Iterable
的支持相对较少,你需要跨越一些障碍。(不详细解释,这是由于Java泛型的机制导致的——稍后我会发布一些更详细的链接)。
(假设你正在使用泛型,例如Map<String, String>
而不是简单的Map
)。
同时,您有几个选项...
如果你接受会引发警告的测试代码或者在你的测试中使用@SuppressWarnings("unchecked")
:
assertThat(actualMap.entrySet(), (Matcher)hasItems(expectedMap.entrySet().toArray()));
解释:没有重载接受Set
或Iterable
的hasItems
方法,但会接受数组。Set.toArray()
返回Object[]
,它与你的actualMap.entrySet()
不匹配,无法通过assertThat
断言。但是,如果你抹掉Matcher的声明类型,它就可以顺利进行。
如果你想要一个不带警告编译的断言,情况就会变得更加复杂 - 你需要将Set
复制到某种Iterable<Object>
中(你不能强制转换),以便匹配对象:
assertThat(new HashSet<Object>(actualMap.entrySet()), hasItems(expectedMap.entrySet().toArray()));
老实说,为了清晰起见,你几乎可以肯定地最好逐个声明每个条目:
for (Entry<String, String> entry : expectedMap.entrySet()) {
assertThat(actualMap, hasEntry(entry.getKey(), entry.getValue()));
}
或者你可以编写自己的 Matcher - 在网上和 SO 上有很多关于如何做到这一点的资源。