2014-06-17 53 views
9

說我有一類這樣的:如何使用assertj執行鍵和值的更深層次的匹配

public class Character { 
    public Character(String name){ 
     this.name = name; 
    } 
    private String name; 
    public String getName() { return name; } 
} 

後來,一個地圖

Map<Character, Integer> characterAges = new HashMap<Character, Integer>(); 
characterAges.put(new Character("Frodo"), 34); 

使用assertj,什麼是最好的方式測試characterAges包含「佛羅多」字符?對於年齡,我可以這樣做:

assertThat(characterAges).hasValue(34); 

而且我知道我可以這樣做:

assertThat(characterAges.keySet()) 
       .extracting("name") 
       .contains("Frodo"); 

但後來我失去了我的流暢性。我真的希望它是這樣的:

assertThat(characterAges) 
       .hasKey(key.extracting("name").contains("Frodo") 
       .hasValue(34); 

甚至更​​好,這樣我可以確保我的key和value匹配:

assertThat(characterAges) 
       .hasEntry(key.extracting("name").contains("Frodo"), 34); 

是這樣的可能嗎?

回答

5

對此沒有簡單的解決方案。一種方法是實現字符映射的custom Assertion。以下是此問題的一個簡單的自定義斷言例如:

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

} 

在測試情況:

assertThat(characterAges).hasNameWithAge("Frodo", 34); 

要知道,你必須爲每一個自定義的數據結構來編寫自己的斷言。對於你的Character類,你可以用AssertJ assertions generator生成一個斷言。


更新的Java 8

與Java 8也可以在Lambda表達式中使用

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" 
    ); 
+0

不錯的解決方案,約翰 - 謝謝。 – pduncan

相關問題