【问题标题】:Using hamcrest to match Map contains entries of different types使用 hamcrest 匹配 Map 包含不同类型的条目
【发布时间】:2015-07-25 00:42:19
【问题描述】:

假设我有一张地图:

Map<String,Object> map1 = new HashMap<String,Object>();
map1.put("foo1","foo1");
map1.put("foo2", Arrays.asList("foo2","bar2"));

现在我想使用 Hamcrest 匹配器来验证地图的值。如果这是一个 Map 我会做类似的事情:

assertThat(map1, hasEntry("foo1", "foo1"));

但是,在尝试将其与 Map 一起使用时,我遇到了困难,其中 Map 中的条目可能是字符串或值列表。这适用于第一个条目:

assertThat(map1, hasEntry("foo1", (Object)"foo1"));

对于第二个条目,我不知道如何设置匹配器。

编辑:

我也试过了,但它会产生编译器警告。

assertThat(
            map1,
            hasEntry(
                    "foo2",
                    contains(hasProperty("name", is("foo2")),
                            hasProperty("name", is("bar2")))));

“Assert类型中的方法assertThat(T, Matcher)不适用于参数(Map, Matcher>>>)”

(以上是这里的解决方案:Hamcrest compare collections

【问题讨论】:

  • 你使用什么版本的 Java?
  • JDK 1.7 版

标签: java unit-testing junit hamcrest


【解决方案1】:

这样试试 你可以使用 ImmutableMap

 assertThat( actualValue,
            Matchers.<Map<String, Object>>equalTo( ImmutableMap.of(
                "key1", "value",
                "key2", "arrayrelated values"
) ) );

希望它对你有用。

【讨论】:

  • 这里的想法是使用 Hamcrest,而不是这样做。虽然这种方法可以没有 Hamcrest,但我怀疑这就是 OP 正在寻找的。​​span>
  • @Makoto 我更新了我的答案,它符合基于 Hemcrest Matcher 的要求
  • 我发现此提案存在多个问题。首先,您必须使用(Object)转换值,其次我不明白您如何尝试在“key2”的值中显示集合...
  • 这似乎有效:assertThat(map1, Matchers.> equalTo(ImmutableMap.of("foo1", (Object) "foo1", "foo2", (Object ) Arrays.asList("foo2","bar2"))));
  • 知道如何让它与返回的实际值的随机排序一起工作吗?
【解决方案2】:

你不能用 Hamcrest hasEntry 优雅地做到这一点,因为当你尝试在列表上使用匹配器时它会进行类型检查。我认为最简单的选择是这样做:

@Test
public void test() {
    Map<String, Object> map1 = new HashMap<>();
    map1.put("foo1", "foo1");
    map1.put("foo2", Arrays.asList("foo2", "bar2"));

    assertThat(map1, hasEntry("foo1", "foo1"));
    assertThat(map1, hasListEntry(is("foo2"), containsInAnyOrder("foo2", "bar2")));
}

@SuppressWarnings("unchecked")
public static org.hamcrest.Matcher<java.util.Map<String, Object>> hasListEntry(org.hamcrest.Matcher<String> keyMatcher, org.hamcrest.Matcher<java.lang.Iterable<?>> valueMatcher) {
    Matcher mapMatcher = org.hamcrest.collection.IsMapContaining.<String, List<?>>hasEntry(keyMatcher, valueMatcher);
    return mapMatcher;
}

hasListEntry 在这里只是为了防止编译器错误。它执行未经检查的分配,这就是您需要@SuppressWarnings("unchecked") 的原因。例如,您可以将此静态方法放在常用的测试工具中。

【讨论】:

  • 我必须做的唯一改变是 containsInAnyOrder((Object)"foo2",(Object) "bar2")... 不知道为什么,因为字符串是对象。
  • @acvcu:这是因为您从地图中检索的项目是Object,而不是String。是的,它们仍然是String 实例,但它们被视为Object(类似于Object entry = "foo";)。
猜你喜欢
  • 2018-10-07
  • 2015-09-15
  • 2023-03-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多