说我有这样一个类:
public class Character {
public Character(String name){
this.name = name;
}
private String name;
public String getName() { return name; }
}
Run Code Online (Sandbox Code Playgroud)
后来,一张地图
Map<Character, Integer> characterAges = new HashMap<Character, Integer>();
characterAges.put(new Character("Frodo"), 34);
Run Code Online (Sandbox Code Playgroud)
使用assertj,测试该字符的最佳方法是什么包括"佛罗多"字符?对于这个年龄,我可以这样做:
assertThat(characterAges).hasValue(34);
Run Code Online (Sandbox Code Playgroud)
我知道我能做到:
assertThat(characterAges.keySet())
.extracting("name")
.contains("Frodo");
Run Code Online (Sandbox Code Playgroud)
但后来我失去了流利.我真正想要的是这样的:
assertThat(characterAges)
.hasKey(key.extracting("name").contains("Frodo")
.hasValue(34);
Run Code Online (Sandbox Code Playgroud)
或者甚至更好,以便我可以确保我的密钥和值匹配:
assertThat(characterAges)
.hasEntry(key.extracting("name").contains("Frodo"), 34);
Run Code Online (Sandbox Code Playgroud)
这样的事情可能吗?
你也可以这样做:
assertThat(characterAges).contains(entry("Frodo", 34), ...);
Run Code Online (Sandbox Code Playgroud)
请参阅https://github.com/joel-costigliola/assertj-core/wiki/New-and-noteworthy#new-map-assertions
小智 6
AbstractMapAssert的以下方法将适合您:
containsExactlyEntriesOf验证实际映射是否仅包含给定映射的条目,而不包含其他内容(按 order )。这应该与 TreeMap 一起使用。HashMap 不保证顺序,你的测试会随机失败。
containsExactlyInAnyOrderEntriesOf验证实际映射是否仅包含给定的条目,不包含任何其他条目(按任何顺序)。这将与 HashMap 一起使用。
import java.util.Map;
import org.assertj.core.api.Assertions;
import org.junit.jupiter.api.Test;
public class TestMapAssertions {
@Test
public void testCreateMap() {
//Call
Map<String, String> actual = ClassUnderTest.createMap();
//Assert
Assertions.assertThat(actual).containsExactlyInAnyOrderEntriesOf(
Map.of("Key1", "Value1", "Key2", "Value2")
);
}
public static class ClassUnderTest {
public static Map<String, String> createMap() {
return Map.of("Key1", "Value1", "Key2", "Value2");
}
}
}
Run Code Online (Sandbox Code Playgroud)
对此没有简单的解决方案.一种方法是为角色映射实现自定义断言.以下是此问题的简单自定义断言示例:
public class CharacterMapAssert extends AbstractMapAssert<MapAssert<Character, Integer>, Map<Character, Integer>, Character, Integer> {
public CharacterMapAssert(Map<Character, Integer> actual) {
super(actual, CharacterMapAssert.class);
}
public static CharacterMapAssert assertThat(Map<Character, Integer> actual) {
return new CharacterMapAssert(actual);
}
public CharacterMapAssert hasNameWithAge(String name, int age) {
isNotNull();
for (Map.Entry<Character, Integer> entrySet : actual.entrySet()) {
if (entrySet.getKey().getName().contains(name) && (int) entrySet.getValue() == age) {
return this;
}
}
String msg = String.format("entry with name %s and age %s does not exist", name, age);
throw new AssertionError(msg);
}
}
Run Code Online (Sandbox Code Playgroud)
在测试用例中:
assertThat(characterAges).hasNameWithAge("Frodo", 34);
Run Code Online (Sandbox Code Playgroud)
请注意,您必须为每个自定义数据结构编写自己的断言.对于你Character的类,你可以生成与一个断言AssertJ断言发生器.
更新Java 8
使用Java 8也可以使用Lambda Expression
assertThat(characterAges).matches(
(Map<Character, Integer> t)
-> t.entrySet().stream().anyMatch((Map.Entry<Character, Integer> t1)
-> "Frodo".equals(t1.getKey().getName()) && 34 == t1.getValue()),
"is Frodo and 34 years old"
);
Run Code Online (Sandbox Code Playgroud)
从 3.6.0 开始,您可以使用hasEntrySatisfying:
assertThat(characterAges)
.hasSize(1)
.hasEntrySatisfying(aKey, e ->
assertThat(e)
.isEqualTo(99.99)
);
Run Code Online (Sandbox Code Playgroud)
在您的情况下,如果您无法使用键进行查找,您可以使用基于条件的hasEntrySatisfying(更详细)。