如何声明一个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, "));