如何声明一个Iterable包含具有某个属性的元素?

假设我想用这个签名unit testing一个方法:

List<MyItem> getMyItems(); 

假设MyItem是一个有很多属性的Pojo,其中之一是通过getName()访问的"name"

我关心的是, List<MyItem>或任何Iterable包含两个MyItem实例,其"name"属性的值为"foo""bar" 。 如果任何其他属性不匹配,我真的不在乎这个testing的目的。 如果名字匹配,这是一个成功的testing。

如果可能的话,我希望它是单行的。 这是我想做的事情的一些“伪语法”。

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

Hamcrest会对这种事情有好处吗? 如果是这样,那么我的伪语法的最后一个版本是什么?

谢谢@拉赞夫指出我正确的方向。 我能够在一条线上得到它,并成功地追捕了Hamcrest 1.3的import货。

import:

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

尝试:

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

这不是特别Hamcrest,但我觉得这里值得一提。 我在Java8中经常使用的东西是这样的:

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

(编辑Rodrigo Manyari的稍微改进,略less一点,详见评论)

可能有点难以阅读,但我喜欢types和重构的安全性。 它也很酷,用于组合testing多个bean属性。 例如在filterlambda中使用类似java的&&expression式。

Assertj擅长这一点。

 import static org.assertj.core.api.Assertions.assertThat; assertThat(myClass.getMyItems()).extracting("name").contains("foo", "bar"); 

与hamcrest相比,assertj的优点是可以很容易地使用代码完成。

只要你的List是一个具体的类,只要你在MyItem上实现了equals()方法,你可以直接调用contains()方法。

 // 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"))); 

假设你已经实现了一个接受你想断言的值的构造函数。 我意识到这不是一个单一的行,但是知道哪个值丢失而不是一次检查两个是有用的。

我会用类似的东西

 String s = myClass.getMyItems().toString(); assertTrue(s.contains(", name=foo, ") && s.contains(", name=bar, "));