Коллекция Hamcrest, в которой объекты в списке имеют поле, совпадающее со значениями в другом списке - PullRequest
0 голосов
/ 12 декабря 2018

У меня есть тестируемый метод, который возвращает список объектов ... например, объект «Person».

У меня есть список «Ожидаемые имена» для проверки результата.

В настоящее время у меня есть рабочий тест, который перебирает имена в «Ожидаемые имена» и утверждает, что каждый из них содержится в списке объектов «Персона».Вот так (учтите, что следующий фрагмент кода есть в Kotlin):

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

Это прекрасно работает, когда утверждение проходит, и проверяет мой метод.Тем не менее, это очень громоздко, когда тест не пройден, потому что он быстро проваливается, как только встречает пропущенное имя и не утверждает остальные имена.Я бы предпочел улучшить свое утверждение, чтобы сообщать обо всех пропущенных именах одновременно, а не по одному за раз.

Что-то вроде:

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

Я хочу, чтобы мое сообщение assertionFailure былочто-то вроде:

Ожидается, что список, соответствующий всем «Смит, Джонс, Дэвис», но [«Смит», «Дэвис»] не найден в «Person [firstName = John, lastName =»Джонс "], Person [firstName = Sarah, lastName = Jones]"

Если в результатах присутствуют дополнительные объекты Person со значениями lastName, которые не включены в "Ожидаемые имена_посланий", это все равно должно пройти какПока ВСЕ имена из «Ожидаемые имена» представлены в результатах.

Также важно знать, что это параметризованный тест Junit5, а «ожидаемые имена» - один из передаваемых параметров.в. Так что я не могу просто жестко закодировать фамилии в утверждении.

Есть ли средство сопоставления коллекции Hamcrest, которое будет делать то, что я хочу?Или, если нет, кто-нибудь может заставить меня начать с нестандартного сопоставителя, который это сделает?

Любая помощь приветствуется.

1 Ответ

0 голосов
/ 19 декабря 2018

Вы можете сделать это с помощью предоставленных совпадений подколенных сухожилий для Iterable:

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)
...