2012-08-28 30 views
70

假設欲單元測試與此簽名的方法:如何聲明一個Iterable包含具有某個屬性的元素?

List<MyItem> getMyItems(); 

MyItem假設是具有許多屬性一個POJO,其中之一是"name",經由getName()訪問。

。我只關心確認的是,List<MyItem>,或任何Iterable,包含兩個MyItem情況下,其"name"屬性有值"foo""bar"。如果任何其他屬性不匹配,我並不真正關心此測試的目的。如果名字匹配,這是一個成功的測試。

如果可能,我希望它是一行代碼。這是我想要做的事情的一些「僞語法」。

assert(listEntriesMatchInAnyOrder(myClass.getMyItems(), property("name"), new String[]{"foo", "bar"}); 

Hamcrest會對這類事情有好處嗎?如果是這樣,那麼我的僞語法的最後一個版本是什麼?

回答

76

謝謝@Razvan指出我正確的方向。我能夠在一條線上獲得它,併成功地爲Hamcrest 1.3追蹤進口貨物。

進口:

import static org.hamcrest.CoreMatchers.is; 
import static org.hamcrest.Matchers.contains; 
import static org.hamcrest.MatcherAssert.assertThat; 
import static org.hamcrest.beans.HasPropertyWithValue.hasProperty; 

代碼:

assertThat(myClass.getMyItems(), contains(
    hasProperty("name", is("foo")), 
    hasProperty("name", is("bar")) 
)); 
38

嘗試:

assertThat(myClass.getMyItems(), 
          hasItem(hasProperty("YourProperty", is("YourValue")))); 
+1

就像一個邊節點 - 這是一個hamcrest解決方案(不assertj) – Hartmut

3

只要你的列表是一個具體的類,可以簡單,只要調用contains()方法爲您實現您的equals()方法上MyItem。

// given 
// some input ... you to complete 

// when 
List<MyItems> results = service.getMyItems(); 

// then 
assertTrue(results.contains(new MyItem("foo"))); 
assertTrue(results.contains(new MyItem("bar"))); 

假設您已經實現了一個構造函數,該構造函數接受要斷言的值。我意識到這不是一條線,但知道缺少哪個值而不是一次檢查兩者是有用的。

+0

我真的很喜歡你的解決方案,但他應該修改所有代碼的測試嗎? –

+0

我想這裏的每個答案都需要一些測試設置,執行要測試的方法,然後聲明屬性。從我所能看到的答案來看,沒有真正的開銷,只是我有兩條關於seaprate行的斷言,因此失敗的斷言可以清楚地標識缺失的值。 – Brad

+0

最好還在assertTrue中包含一條消息,以便錯誤消息更易理解。沒有消息,如果失敗,JUnit將只是拋出一個AssertionFailedError而沒有任何錯誤消息。所以最好包含「結果」這樣的內容應該包含新的MyItem(\「foo \」)「。 – Max

21

它不是特別Hamcrest,但我認爲它值得在此一提。我在Java8經常使用的是一樣的東西:

assertTrue(myClass.getMyItems().stream().anyMatch(item -> "foo".equals(item.getName()))); 

(。編輯,以羅德里戈Manyari的輕微改善這有點不太詳細見註釋)

它可能是一個有點難以閱讀,但我喜歡類型和重構的安全性。 它同樣很酷,可以組合測試多個bean屬性。例如在濾波器lambda中使用類似java的& &表達式。

+2

稍微改進: assertTrue(myClass.getMyItems()。stream()。anyMatch(item - >「foo」.equals(item.getName ))); –

+0

@RodrigoManyari,缺少圓括號 – Abdull

15

Assertj擅長這一點。

import static org.assertj.core.api.Assertions.assertThat; 

    assertThat(myClass.getMyItems()).extracting("name").contains("foo", "bar"); 

assertj與hamcrest相比,更容易使用代碼完成。

相關問題