我想检查地图是否包含某组条目。允许包含不在expectedMap
中的其他条目。我目前有以下断言:
assertThat(expectedMap.entrySet(), everyItem(isIn(actualMap.entrySet())));
尽管这确实有效,但它打印的失败消息令人困惑,因为预期和接收的参数已从正常使用中反转。有没有更好的方法来写它?
答案 0 :(得分:8)
hasItems
做你想要的,但是以一种非显而易见的方式。你必须跳过一些箍,因为Hamcrest对匹配Iterable
的支持相对有限。 (没有详细说明,这是由于Java泛型如何工作的变幻莫测 - 我将在稍后发布一些更详细的链接。)
(我假设您使用的是泛型,例如Map<String, String>
,而不是Map
。)
与此同时,您有几个选择......
如果您对在测试中使用@SuppressWarnings("unchecked")
发出警告的测试代码感到满意:
assertThat(actualMap.entrySet(), (Matcher)hasItems(expectedMap.entrySet().toArray()));
说明:hasItems
没有重载需要Set
或Iterable
,但需要一个数组。 Set.toArray()
会返回Object[]
,但assertThat
与您的actualMap.entrySet()
不匹配 - 但如果您删除了匹配器的声明类型,则会很乐意继续进行。
如果你想要一个在没有警告的情况下进行编译的断言,它会变得更加丑陋 - 你需要将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()));
}
...或者你可以编写自己的匹配器 - 有很多关于如何在线和在线进行此操作的资源。