Java 如何断言 Map 包含带有条目的 Map
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/31523800/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to assert Map contains Map with entry
提问by Jeff E
I have a unit test that needs to check for a nested map value. I can get my assertion to work by pulling out the entry and matching the underlying Map
, but I was looking for a clear way to show what the assertion is doing. Here is a very simplified test:
我有一个需要检查嵌套映射值的单元测试。我可以通过拉出条目并匹配底层 使我的断言起作用Map
,但我一直在寻找一种清晰的方法来显示断言正在做什么。这是一个非常简单的测试:
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.hasEntry;
import java.util.HashMap;
import java.util.Map;
import org.junit.Test;
public class MapContainsMapTest {
@Test
public void testMapHasMap() {
Map<String, Object> outerMap = new HashMap<String, Object>();
Map<String, Object> nestedMap = new HashMap<String, Object>();
nestedMap.put("foo", "bar");
outerMap.put("nested", nestedMap);
// works but murky
assertThat((Map<String, Object>) outerMap.get("nested"), hasEntry("foo", "bar"));
// fails but clear
assertThat(outerMap, hasEntry("nested", hasEntry("foo", "bar")));
}
}
It seems the problem is the outer map is being compared using hasEntry(K key, V value)
while what I want to use is hasEntry(Matcher<? super K> keyMatcher, Matcher<? super V> valueMatcher)
. I am not sure how to coerce the assertion to use the second form.
似乎问题是正在比较外部地图,hasEntry(K key, V value)
而我想要使用的是hasEntry(Matcher<? super K> keyMatcher, Matcher<? super V> valueMatcher)
. 我不确定如何强制断言使用第二种形式。
Thanks in advance.
提前致谢。
采纳答案by Florian Schaetz
I would probably extend a new Matcher for that, something like that (beware, NPEs lurking):
我可能会为此扩展一个新的匹配器,类似的东西(当心,潜伏的 NPE):
class SubMapMatcher extends BaseMatcher<Map<?,?>> {
private Object key;
private Object subMapKey;
private Object subMapValue;
public SubMapMatcher(Object key, Object subMapKey, Object subMapValue) {
super();
this.key = key;
this.subMapKey = subMapKey;
this.subMapValue = subMapValue;
}
@Override
public boolean matches(Object item) {
Map<?,?> map = (Map<?,?>)item;
if (!map.containsKey(key)) {
return false;
}
Object o = map.get(key);
if (!(o instanceof Map<?,?>)) {
return false;
}
Map<?,?> subMap = (Map<?,?>)o;
return subMap.containsKey(subMapKey) && subMap.get(subMapKey).equals(subMapValue);
}
@Override
public void describeTo(Description description) {
description.appendText(String.format("contains %s -> %s : %s", key, subMapKey, subMapValue));
}
public static SubMapMatcher containsSubMapWithKeyValue(String key, String subMapKey, String subMapValue) {
return new SubMapMatcher(key, subMapKey, subMapValue);
}
}
回答by David Pérez Cabrera
If You declare outerMap as Map<String, Map<String, Object>>
you don't need the ugly cast. Like this:
如果您声明外层映射,因为Map<String, Map<String, Object>>
您不需要丑陋的演员表。像这样:
public class MapContainsMapTest {
@Test
public void testMapHasMap() {
Map<String, Map<String, Object>> outerMap = new HashMap<>();
Map<String, Object> nestedMap = new HashMap<>();
nestedMap.put("foo", "bar");
outerMap.put("nested", nestedMap);
assertThat(outerMap.get("nested"), hasEntry("foo", "bar"));
}
}
回答by eee
If you only want to put Map<String, Object>
as values in your outerMap
adjust the declaration accordingly. Then you can do
如果您只想Map<String, Object>
在您outerMap
的声明中添加值,请相应地调整声明。然后你可以做
@Test
public void testMapHasMap() {
Map<String, Map<String, Object>> outerMap = new HashMap<>();
Map<String, Object> nestedMap = new HashMap<String, Object>();
nestedMap.put("foo", "bar");
outerMap.put("nested", nestedMap);
Object value = "bar";
assertThat(outerMap, hasEntry(equalTo("nested"), hasEntry("foo", value)));
}
Object value = "bar";
is necessary for compile reasons. Alternatively you could use
Object value = "bar";
出于编译原因是必要的。或者你可以使用
assertThat(outerMap,
hasEntry(equalTo("nested"), Matchers.<String, Object> hasEntry("foo", "bar")));