Junit 如何使用Hamcrest检查地图项目

Junit 如何使用Hamcrest检查地图项目,junit,hamcrest,Junit,Hamcrest,我最近一直在使用Hamcrest库编写一些测试,非常成功,但现在我需要做一些更复杂的事情,并开始看到很多困难。我需要输入并验证地图中项目的属性。我的生产代码如下所示: Map<String, List<MyItem>> map = new HashMap<String, List<MyItem>>(); map.put("one", Arrays.asList(new MyItem("One"))); map.put("tw

我最近一直在使用Hamcrest库编写一些测试,非常成功,但现在我需要做一些更复杂的事情,并开始看到很多困难。我需要输入并验证地图中项目的属性。我的生产代码如下所示:

    Map<String, List<MyItem>> map = new HashMap<String, List<MyItem>>();
    map.put("one", Arrays.asList(new MyItem("One")));
    map.put("two",  Arrays.asList(new MyItem("Two")));
    map.put("three",  Arrays.asList(new MyItem("Three")));
Map Map=newhashmap();
map.put(“一”,Arrays.asList(新的MyItem(“一”));
map.put(“两个”,array.asList(新的MyItem(“两个”));
map.put(“三”,array.asList(新的MyItem(“三”));
我想写一些如下的测试代码,但它不能编译。看起来Hamcrest的hasEntry是类型参数化的,而hasItem和hasProperty只期望对象

    assertThat(map, Matchers.<String, List<MyItem>>hasEntry("one",  hasItem(hasProperty("name", is("One")))));
assertThat(map,Matchers.hasEntry(“一”),hasItem(hasProperty(“名称”,is(“一”)));

我的IDE(Eclipse)给出了这个错误消息:类型为
Matchers
的参数化方法
hasEntry(String,List)
不适用于参数
(String,Matcher),因此为了简化此过程,您可以尝试以下方法

assertThat((Object)map, (Matcher)Matchers.hasEntry("one",  hasItem(hasProperty("name", is("One")))));
通过使用原始类型,您将得到一个警告,但不会出现编译错误。如果您在过去使用过此技巧,我不想担心如何使所有类型转换都适合编译器


也可以考虑使用<代码> ItErababLeCon。这将验证整个列表,如果

MyItem
实现
equals
,则您将不会在测试中使用反射。

您可以使用
包含
包含任意顺序。确实,您必须以这种方式列出
列表中的所有项目,但它比
hasItem
更简洁:

@SuppressWarnings("unchecked")
@Test
public void mapTest() {
  Map<String, List<MyItem>> map = new HashMap<String, List<MyItem>>();
  map.put("one", asList(new MyItem("1"), new MyItem("one")));

  assertThat(map, hasEntry(is("one"),
                           containsInAnyOrder(hasProperty("name", is("one")),
                                              hasProperty("name", is("1")))));
}
@SuppressWarnings(“未选中”)
@试验
公共void映射测试(){
Map Map=newhashmap();
map.put(“一”)、asList(新MyItem(“一”)、新MyItem(“一”));
资产(map,hasEntry)(即“一”),
containsInAnyOrder(hasProperty(“名称”),is(“一”),
hasProperty(“名称”,为(“1”));
}

由于@t0mppa没有提供一个关于如何使用Hamcrest的
contains
containsInAnyOrder
的好例子,这里有一些小东西可以让您开始:

Map<Integer, String> columns = new HashMap<Integer, String>();
columns.put(1, "ID");
columns.put(2, "Title");
columns.put(3, "Description");

assertThat(columns.values(), contains("ID", "Title", "Description")); // passes
assertThat(columns.values(), contains("ID", "Description", "Title")); // fails
assertThat(columns.values(), containsInAnyOrder("ID", "Description", "Title")); // passes
Map columns=newhashmap();
列。放入(1,“ID”);
列。投入(2,“标题”);
第3栏,“说明”);
资产(columns.values(),包含(“ID”、“Title”、“Description”);//通行证
资产(columns.values(),包含(“ID”、“Description”、“Title”);//失败
资产(columns.values(),包含任意顺序(“ID”、“说明”、“标题”);//通行证

请注意,与
hasItem
hasItems
相反,只有当您为它们提供了所有要匹配的值的完整列表时,它们才会起作用。有关更多信息,请参见Hamcrest's。

hasEntry
方法有两个签名:

  • hasEntry(键、值)
  • hasEntry(匹配器,匹配器)
您正在使用第一个签名,因此您正在检查映射是否包含映射到字符串“one”的匹配器。正在使用第二个签名,这就是它工作的原因。好消息是,您不需要列出列表中的所有元素,只需

assertThat(map, hasEntry(is("one"), hasItem(hasProperty("name", is("One")))));

我不相信这会解决编译时错误,因为
hasEntry
将返回一个
Matcher
而不是所需的
Matcher
@JohnB:信不信由你,但我试过了,它对我来说效果很好。它是否也适用于具有不同类型值的map(用java来说是
map
)?因为我正在用mockito进行尝试,我遇到了一个
重载解析失败的
编译错误。