如何断言地图包含带有条目的地图
How to assert Map contains Map with entry
我有一个单元测试需要检查嵌套映射值。我可以通过拉出条目并匹配底层 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")));
}
}
问题似乎是外部地图正在使用 hasEntry(K key, V value)
进行比较,而我想使用的是 hasEntry(Matcher<? super K> keyMatcher, Matcher<? super V> valueMatcher)
。我不确定如何强制断言使用第二种形式。
提前致谢。
我可能会为此扩展一个新的匹配器,类似的东西(注意,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);
}
}
如果您将 outerMap 声明为 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"));
}
}
如果您只想将 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";
是必需的。或者你可以使用
assertThat(outerMap,
hasEntry(equalTo("nested"), Matchers.<String, Object> hasEntry("foo", "bar")));
这样试试:
assertThat(nestedMap).contains(Map.entry("foo", "bar"));
assertThat(outerMap).contains(Map.entry("nested", nestedMap));
我有一个单元测试需要检查嵌套映射值。我可以通过拉出条目并匹配底层 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")));
}
}
问题似乎是外部地图正在使用 hasEntry(K key, V value)
进行比较,而我想使用的是 hasEntry(Matcher<? super K> keyMatcher, Matcher<? super V> valueMatcher)
。我不确定如何强制断言使用第二种形式。
提前致谢。
我可能会为此扩展一个新的匹配器,类似的东西(注意,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);
}
}
如果您将 outerMap 声明为 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"));
}
}
如果您只想将 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";
是必需的。或者你可以使用
assertThat(outerMap,
hasEntry(equalTo("nested"), Matchers.<String, Object> hasEntry("foo", "bar")));
这样试试:
assertThat(nestedMap).contains(Map.entry("foo", "bar"));
assertThat(outerMap).contains(Map.entry("nested", nestedMap));