2014-01-17 28 views
4

我想檢查一個地圖是否包含特定的一組條目。允許包含不在expectedMap中的其他條目。目前,我有以下斷言:Hamcrest測試地圖包含來自另一個地圖的所有條目

assertThat(expectedMap.entrySet(), everyItem(isIn(actualMap.entrySet()))); 

雖然這樣做的工作,它打印的失敗消息是混亂的,因爲預期和接受的論點已經從正常使用逆轉。有沒有更好的方法來寫它?

回答

5

hasItems做你想做的,但以一種不明顯的方式。由於Hamcrest對匹配Iterable的支持相對有限,因此您必須跳過一些環節。 (沒有詳細說明,這是由於Java泛型如何工作的變幻莫測 - 我將在稍後發佈一些更詳細的鏈接)。

(我假設您使用的是泛型,例如Map<String, String>而不是簡單的Map)。

在你有幾個選項的同時...

如果你是幸福的,使用在測試@SuppressWarnings("unchecked")提出了警告/測試代碼:

assertThat(actualMap.entrySet(), (Matcher)hasItems(expectedMap.entrySet().toArray())); 

說明:沒有超載的hasItems需要SetIterable,但它會佔用一個數組。 Set.toArray()返回Object[],它不會與assertThatactualMap.entrySet()匹配 - 但是如果您擦除匹配器的聲明類型,它將會愉快地繼續。

如果你想,如果沒有警告編譯斷言,它變得醜陋 - 你需要的Set複製到某種Iterable<Object>(你可以不投),以匹配的對象:

assertThat(new HashSet<Object>(actualMap.entrySet()), hasItems(expectedMap.entrySet().toArray())); 

但要完全誠實的,爲了清楚你幾乎肯定是最好關閉單獨斷言每個條目:

for (Entry<String, String> entry : expectedMap.entrySet()) { 
    assertThat(actualMap, hasEntry(entry.getKey(), entry.getValue())); 
} 

...或者你可以寫自己的匹配 - 有豐富的資源如何做到這一點在線在SO上。

+0

是的,我問的一個原因是因爲我不滿意警告或演員。它很醜。我同意現在最好的選擇可能是最好的。我過去寫過一些匹配器,如果我需要再做一次,我會爲它寫一個。 –

相關問題