Java 使用Hamcrest映射相等

Java 使用Hamcrest映射相等,java,collections,hamcrest,Java,Collections,Hamcrest,我想使用hamcrest来断言两个映射是相等的,即它们有相同的一组指向相同值的键 我目前的最佳猜测是: assertThat( affA.entrySet(), hasItems( affB.entrySet() ); 其中: 类型Assert中的方法assertThat(T,Matcher)不适用于参数(Set,Matcher) 我还研究了containsAll的变体,以及hamcrest软件包提供的其他一些变体。谁能给我指出正确的方向吗?或者我必须编写自定义匹配器吗?有时Map.equal

我想使用hamcrest来断言两个映射是相等的,即它们有相同的一组指向相同值的键

我目前的最佳猜测是:

assertThat( affA.entrySet(), hasItems( affB.entrySet() );
其中:

类型
Assert
中的方法
assertThat(T,Matcher)
不适用于参数(
Set,Matcher

我还研究了
containsAll
的变体,以及hamcrest软件包提供的其他一些变体。谁能给我指出正确的方向吗?或者我必须编写自定义匹配器吗?

有时
Map.equals()
就足够了。但有时您不知道被测试代码返回的
Map
s的类型,因此您不知道
.equals()
是否会正确地将代码返回的未知类型的映射与您构建的映射进行比较。或者,您不想将代码与此类测试绑定在一起

此外,单独构建一张地图以将结果与之进行比较并不十分优雅:

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));

还有另一种变体
hasEntry()
,它将匹配器作为参数,而不是键和值的精确值。如果您需要对每个键和值进行相等性测试以外的其他测试,这将非常有用。

我想出的最短方法是两条语句:

assertThat( affA.entrySet(), everyItem(isIn(affB.entrySet())));
assertThat( affB.entrySet(), everyItem(isIn(affA.entrySet())));
但你也可以这样做:

assertThat(affA.entrySet(), equalTo(affB.entrySet()));
取决于映射的实现,牺牲差异报告的清晰性:这只会告诉您存在差异,而上面的语句也会告诉您是哪一种差异

更新:实际上有一条语句独立于集合类型工作:

assertThat(affA.entrySet(), both(everyItem(isIn(affB.entrySet()))).and(containsInAnyOrder(affB.entrySet())));
我喜欢使用。它们支持
Map.equals()
,并且易于构造。唯一的技巧是显式指定类型参数,因为hamcrest将采用
ImmutableMap
类型

assertThat( actualValue,
            Matchers.<Map<String, String>>equalTo( ImmutableMap.of(
                "key1", "value",
                "key2", "other-value"
) ) );
assertThat(实际值,
Matchers.equalTo(不可变映射)(
“键1”,“值”,
“键2”,“其他值”
) ) );

现在另一个可用的选项是使用for Hamcrest。它有(以及其他番石榴“系列”的配对品)。 根据您的示例,它将是:

assertThat(affA, hasSameKeySet(affB));
对于基于JDK7的项目,可以使用以下依赖项:

<dependency>
  <groupId>it.ozimov</groupId>
  <artifactId>java7-hamcrest-matchers</artifactId>
  <version>0.7.0</version>
</dependency>

是奥齐莫夫
java7 hamcrest匹配器
0.7.0
或者,如果您使用的是JDK8或更高版本,请执行以下操作:

<dependency>
  <groupId>it.ozimov</groupId>
  <artifactId>java8-hamcrest-matchers</artifactId>
  <version>0.7.0</version>
</dependency>

是奥齐莫夫
java8 hamcrest匹配器
0.7.0

Hamcrest现在有一个用于尺码收集的
匹配器


org.hamcrest.collection.IsCollectionWithSize

这就像一个符咒,不需要像公认答案那样的两个断言

assertThat( actualData.entrySet().toArray(), 
    arrayContainingInAnyOrder(expectedData.entrySet().toArray()) );

如果需要将一组结果与期望值进行比较,并且选择使用库,则可以执行以下操作:

// 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);
//按测试键放置一组期望值
映射期望=。。。;
//对于每个测试键,获取结果
Map results=expections.keySet().stream().collect(toMap(k->k,k->getYourProductionResult(k));
资产(结果)。包含所有(预期)分录;
请注意,
containsAllEntriesOf
不会比较贴图是否相等。如果生产代码实际返回一个
Map
,则可能需要添加一个检查键
assertThat(results)。containsOnlyKeys((K[])expections.keySet().toArray());

一个非常简单的方法是使用Guava的com.google.common.collect.Maps类中的实用方法

assertThat(Maps.difference(map1,map2).areEqual(),is(true));

我使用groovy和org.hamcrest:hamcrest:2.2进行线程测试

不推荐使用
isIn
方法,建议改用
is(in(…)

然而,
中的
在groovy中是一个关键字

因此,我最终为导入添加了别名:

import static org.hamcrest.Matchers.*
import static org.hamcrest.Matchers.in as matchIn
....
....
@Test
void myTestMethod() {
    Map expectedSubMap = [
            one: "One",
            three: "Three"
            ]
    Map result = getMapToTest()
    assertThat(expectedSubMap.entrySet(), everyItem(is(matchIn(result.entrySet()))))
}

我也尝试过
containsAll
等。不久前,它似乎不起作用-显然,hamcrest有点不可靠:-(有什么原因不能使用Map实现的
.equals()
吗?啊-我没有意识到集合做得很好。equals()比较。一直都是这样吗?这让生活更轻松了!谢谢!这并不能回答最初的问题。与其使用自己的
hasSize
方法,不如使用,
org.hamcrest.collection.IsMapWithSize.aMapWithSize(Matcher这不是只比较键而不比较值吗?这个问题也想比较值。@Hans-PeterStörr博士不,这个问题表明条目集是compared@Taras:报告对
.equals()
没有多大帮助。我必须将对affB的第二次访问转换为数组:
.and(containsInAnyOrder(affB.entrySet().toArray())
合并了
入口集
缺少的
()
和必要的
toArray()
这最终是:
资产(affA.entrySet(),两者(每个项目(isIn(affB.entrySet()))和(包含任何顺序(affB.entrySet().toArray()))
但是,这会删除描述性断言失败,这是使用Hamcrest的主要原因之一。
assertThat(Maps.difference(map1,map2).areEqual(),is(true));
import static org.hamcrest.Matchers.*
import static org.hamcrest.Matchers.in as matchIn
....
....
@Test
void myTestMethod() {
    Map expectedSubMap = [
            one: "One",
            three: "Three"
            ]
    Map result = getMapToTest()
    assertThat(expectedSubMap.entrySet(), everyItem(is(matchIn(result.entrySet()))))
}