如何断言迭代包含具有特定属性的元素?

2022-08-31 07:35:58

假设我想用这个签名对一个方法进行单元测试:

List<MyItem> getMyItems();

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

我所关心的验证是 , 或任何 包含两个实例,其属性具有 值 和 。如果任何其他属性不匹配,我并不真正关心此测试的目的。如果名称匹配,则测试成功。List<MyItem>IterableMyItem"name""foo""bar"

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

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

Hamcrest对这种事情有好处吗?如果是这样,我上面的伪语法的hamcrest版本究竟是什么?


答案 1

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

答案 2

AssertJ提供了一个出色的功能:你可以传递s来提取字段。它在编译时提供检查。
您也可以先轻松断言大小。extracting()Function

它会给:

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

Assertions.assertThat(myClass.getMyItems())
          .hasSize(2)
          .extracting(MyItem::getName)
          .containsExactlyInAnyOrder("foo", "bar"); 

containsExactlyInAnyOrder()断言列表仅包含这些值,无论顺序如何。

要断言列表包含这些值,无论顺序如何,但也可能包含其他值,请使用:contains()

.contains("foo", "bar"); 

作为旁注:要从一个的元素断言多个字段,使用AssertJ,我们通过将每个元素的预期值包装到一个函数中来做到这一点:Listtuple()

import static org.assertj.core.api.Assertions;
import static org.assertj.core.groups.Tuple;

Assertions.assertThat(myClass.getMyItems())
          .hasSize(2)
          .extracting(MyItem::getName, MyItem::getOtherValue)
          .containsExactlyInAnyOrder(
               tuple("foo", "OtherValueFoo"),
               tuple("bar", "OtherValueBar")
           ); 

推荐