使 Hamcrest 匹配 Map 中的键或值
Make Hamcrest to match a key or value in a Map
我为 Hamcrest 和 Map 编写了这个测试程序以使用 Hamcrest Matchers。
该程序独立使用 Hamcrest(不使用 JUnit)。
为什么输出的 none 为真(匹配)?
如何修改此测试程序,使 Map 中的键或值匹配(输出为真)?
import java.util.Map;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import org.hamcrest.Matchers;
import org.hamcrest.collection.IsMapContaining;
public class TestMap {
public static void main(String[] args) {
Map<String, Integer> map = Stream.of(new Object[][] {
{ "data1", 1 },
{ "data2", 2 },
}).collect(Collectors.toMap(data -> (String) data[0], data -> (Integer) data[1]));
for (Map.Entry<String, Integer> entry : map.entrySet()) {
System.out.println("Matchers.hasKey(\"data1\") " + Matchers.hasKey("data1").matches("data1"));
System.out.println("Matchers.hasValue(1) " + Matchers.hasValue(1).matches(1));
System.out.println("IsMapContaining.hasKey(\"data1\") " + IsMapContaining.hasKey("data1").matches("data1"));
System.out.println("IsMapContaining.hasValue(1) " + IsMapContaining.hasValue(1).matches(1));
System.out.println("IsMapContaining.hasEntry(entry.getKey(), entry.getValue()) " + IsMapContaining.hasEntry(entry.getKey(), entry.getValue()));
}
}
}
输出为:
Matchers.hasKey("data1") false
Matchers.hasValue(1) false
IsMapContaining.hasKey("data1") false
IsMapContaining.hasValue(1) false
IsMapContaining.hasEntry(entry.getKey(), entry.getValue()) map containing ["data2"-><2>]
Matchers.hasKey("data1") false
Matchers.hasValue(1) false
IsMapContaining.hasKey("data1") false
IsMapContaining.hasValue(1) false
IsMapContaining.hasEntry(entry.getKey(), entry.getValue()) map containing ["data1"-><1>]
我只解释第一个,其余的你可以自己理解(顺便说一句,这不完全是你的错)。
你认为这里会发生什么:
Matchers.hasKey("data1").matches("data1")
让我们阅读hasKey
的文档:
Creates a matcher for java.util.Map
s matching when the examined java.util.Map
contains at least one key that is equal to the specified key.
现在,让我们阅读 matches
的文档:
This method matches against Object, instead of the generic type T. This is because the caller of the Matcher does not know at runtime what the type is (because of type erasure with Java generics). It is down to the implementations to check the correct type.
理想情况下,您希望 编译器 (javac
) 只允许您在 matches
中指定 Map
(而不是 "data1"
字符串)。毕竟,您确实说过要将 hasKey
与 Map
进行比较,不是吗?但是正如文档中所说:“检查正确类型取决于实现”,javac
不能简单地做到这一点(这是一个限制);你需要自己做。
简而言之,这个 Matchers.hasKey("data1").matches("data1")
甚至不应该编译,但是因为这是 javac
的工作方式(并且因为 hamcrest
像这样设计他们的代码),所以它编译,类型错误。
解决方案很简单:
System.out.println("Matchers.hasKey(\"data1\") " + Matchers.hasKey("data1").matches(map));
注意 matches(map)
...
我为 Hamcrest 和 Map 编写了这个测试程序以使用 Hamcrest Matchers。 该程序独立使用 Hamcrest(不使用 JUnit)。 为什么输出的 none 为真(匹配)? 如何修改此测试程序,使 Map 中的键或值匹配(输出为真)?
import java.util.Map;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import org.hamcrest.Matchers;
import org.hamcrest.collection.IsMapContaining;
public class TestMap {
public static void main(String[] args) {
Map<String, Integer> map = Stream.of(new Object[][] {
{ "data1", 1 },
{ "data2", 2 },
}).collect(Collectors.toMap(data -> (String) data[0], data -> (Integer) data[1]));
for (Map.Entry<String, Integer> entry : map.entrySet()) {
System.out.println("Matchers.hasKey(\"data1\") " + Matchers.hasKey("data1").matches("data1"));
System.out.println("Matchers.hasValue(1) " + Matchers.hasValue(1).matches(1));
System.out.println("IsMapContaining.hasKey(\"data1\") " + IsMapContaining.hasKey("data1").matches("data1"));
System.out.println("IsMapContaining.hasValue(1) " + IsMapContaining.hasValue(1).matches(1));
System.out.println("IsMapContaining.hasEntry(entry.getKey(), entry.getValue()) " + IsMapContaining.hasEntry(entry.getKey(), entry.getValue()));
}
}
}
输出为:
Matchers.hasKey("data1") false
Matchers.hasValue(1) false
IsMapContaining.hasKey("data1") false
IsMapContaining.hasValue(1) false
IsMapContaining.hasEntry(entry.getKey(), entry.getValue()) map containing ["data2"-><2>]
Matchers.hasKey("data1") false
Matchers.hasValue(1) false
IsMapContaining.hasKey("data1") false
IsMapContaining.hasValue(1) false
IsMapContaining.hasEntry(entry.getKey(), entry.getValue()) map containing ["data1"-><1>]
我只解释第一个,其余的你可以自己理解(顺便说一句,这不完全是你的错)。
你认为这里会发生什么:
Matchers.hasKey("data1").matches("data1")
让我们阅读hasKey
的文档:
Creates a matcher for
java.util.Map
s matching when the examinedjava.util.Map
contains at least one key that is equal to the specified key.
现在,让我们阅读 matches
的文档:
This method matches against Object, instead of the generic type T. This is because the caller of the Matcher does not know at runtime what the type is (because of type erasure with Java generics). It is down to the implementations to check the correct type.
理想情况下,您希望 编译器 (javac
) 只允许您在 matches
中指定 Map
(而不是 "data1"
字符串)。毕竟,您确实说过要将 hasKey
与 Map
进行比较,不是吗?但是正如文档中所说:“检查正确类型取决于实现”,javac
不能简单地做到这一点(这是一个限制);你需要自己做。
简而言之,这个 Matchers.hasKey("data1").matches("data1")
甚至不应该编译,但是因为这是 javac
的工作方式(并且因为 hamcrest
像这样设计他们的代码),所以它编译,类型错误。
解决方案很简单:
System.out.println("Matchers.hasKey(\"data1\") " + Matchers.hasKey("data1").matches(map));
注意 matches(map)
...