Hamcrest集合匹配,列表中的对象具有与另一个列表中的值匹配的字段

时间:2018-12-12 17:50:45

标签: junit5 hamcrest

我有一个正在测试的方法,该方法正在返回对象列表……例如“ Person”对象。

我有一个“ expectedLastNames”列表,用于验证结果。

我目前有一个工作测试,该测试循环遍历“ expectedLastNames”中的名称,并断言每个名称都包含在“ Person”对象的列表中。这样(建议在Kotlin中使用以下代码段):

expectedLastNames.forEach { expectedLastName ->
    assertThat(listOfPeople, hasItem(hasProperty("lastName", `is`(expectedLastName.trim()))))
}

当断言通过并验证我的方法时,这很好用。但是,测试失败会非常麻烦,因为一旦遇到缺少的名称且未声明其余名称,它就会快速失败。我希望改进断言,以一次报告所有缺失的名称,而不是一次报告一个。

类似的东西:

assertThat(expectedLastNames, allItems(lastNameMatches(listOfPeople)));

我希望我的assertionFailure消息类似于:

  

预期匹配所有“史密斯,琼斯,戴维斯”的列表,但是在“人[名字=约翰,lastName =“琼斯”]],人[名字=莎拉]中找不到[”史密斯“,”戴维斯“] ,lastName = Jones]“

如果结果中还有其他“姓”值不包含在“ expectedLastNames”中的Person对象,只要在结果中表示“ expectedLastNames”中的所有名称,这应该仍然可以通过。

要知道这是一个Junit5参数化测试,并且“ expectedLastNames”是传递的参数之一也很重要。因此,我不能仅将姓氏硬编码到断言中。

有Hamcrest集合匹配器可以满足我的要求吗?否则,有人可以让我开始使用自定义匹配器吗?

感谢您的帮助。

1 个答案:

答案 0 :(得分:0)

您可以使用提供的Iterable hamcrest匹配器来做到这一点:

import org.junit.Test;

import java.util.List;

import static java.util.Arrays.asList;
import static java.util.stream.Collectors.toList;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.contains;
import static org.hamcrest.Matchers.containsInAnyOrder;

public class MatchValuesInAnotherListTest {
    static class Person{
        private final String firstName;
        private final String lastName;

        Person(String firstName, String lastName) {
            this.firstName = firstName;
            this.lastName = lastName;
        }

        public String getFirstName() {
            return firstName;
        }

        public String getLastName() {
            return lastName;
        }
    }

    @Test
    public void matchLastNames() {
        List<Person> listOfPeople = asList(new Person("Paul", "Smith"), new Person("John", "Davis"));

        assertThat(listOfPeople.stream().map(Person::getLastName).collect(toList()), containsInAnyOrder("Davis", "Smith"));
        assertThat(listOfPeople.stream().map(Person::getLastName).collect(toList()), contains("Smith", "Davis"));
    }
}

他们将提供格式正确的失败消息:

java.lang.AssertionError: 
Expected: iterable over ["Smith"] in any order
     but: Not matched: "Davis"

    at org.hamcrest.MatcherAssert.assertThat(MatcherAssert.java:20)
    at org.hamcrest.MatcherAssert.assertThat(MatcherAssert.java:8)