Сравнение коллекций в Java с помощью Hamcrest matchers

Пройдите тест, узнайте какой профессии подходите
Я предпочитаю
0%
Работать самостоятельно и не зависеть от других
Работать в команде и рассчитывать на помощь коллег
Организовывать и контролировать процесс работы

Быстрый ответ

Для проверки наличия идентичных элементов в коллекциях, не принимая во внимание их порядок, используйте метод containsInAnyOrder из библиотеки Hamcrest:

Java
Скопировать код
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.containsInAnyOrder;

// Сравниваем наборы фруктов: порядок неважен, главное — это сами фрукты!
assertThat(Arrays.asList("яблоко", "банан"), containsInAnyOrder("банан", "яблоко"));

В случаях, когда порядок элементов имеет значение, следует применять contains:

Java
Скопировать код
import static org.hamcrest.Matchers.contains;

// Яблоки идут перед бананами, и именно так и должно быть по алфавиту.
assertThat(Arrays.asList("яблоко", "банан"), contains("яблоко", "банан"));

Эти примеры демонстрируют, как можно использовать Hamcrest matchers для сравнения коллекций.

Пошаговый план для смены профессии

Сопоставление списков на полное совпадение

Если требуется подтвердить полное соответствие двух списков, можно выполнить следующее:

Java
Скопировать код
import static org.junit.Assert.assertEquals;

// Подтверждаем, что яблоки всегда идут перед бананами, как и полагает природа
assertEquals(Arrays.asList("яблоко", "банан"), Arrays.asList("яблоко", "банан"));

Проверка типов: незаметный герой кода

Убедитесь, что тип списка соответствует типу, ожидаемому в matchers:

Java
Скопировать код
List<Agent> agentList = Arrays.asList(new Agent("007"), new Agent("006"));
Matcher<Iterable<? extends Agent>> matcher = containsInAnyOrder(new Agent("006"), new Agent("007"));
assertThat(agentList, matcher); // Незаметно и элегантно, как работа самого агента.

Визуализация

Представьте каждую коллекцию как уникальный набор деталей пазла (🧩):

Markdown
Скопировать код
Коллекция А: [🧩1, 🧩2, 🧩3]
Коллекция B: [🧩3, 🧩4, 🧩5]

Наша цель — найти соответствие между этими двуми коллекциями с помощью Hamcrest:

Markdown
Скопировать код
Matchers.containsInAnyOrder(КоллекцияА, КоллекцияB);

Визуально проверка может выглядеть следующим образом:

Markdown
Скопировать код
🧩 Есть соответствие? 🧩
А: [🧩1, 🧩2, ✅🧩3]
B: [✅🧩3, 🧩4, 🧩5]

отмечает найденные совпадения, а 🧩 показывает уникальные элементы. С помощью Hamcrest порядок элементов не важен.

Поиск «иголки в стоге сена»

В поисках одного элемента

Используйте hasItem, чтобы проверить наличие одного конкретного элемента:

Java
Скопировать код
import static org.hamcrest.Matchers.hasItem;

assertThat(Arrays.asList("яблоко", "банан"), hasItem("яблоко")); // нашли наше "запретное" яблоко

Поиск нескольких элементов

Для проверки нескольких элементов используйте hasItems:

Java
Скопировать код
import static org.hamcrest.Matchers.hasItems;

assertThat(Arrays.asList("яблоко", "банан", "вишня"), hasItems("вишня", "банан")); // больше фруктов, отлично!

Комбинируем матчеры

Матчеры можно сочетать, используя allOf:

Java
Скопировать код
import static org.hamcrest.Matchers.allOf;
import static org.hamcrest.Matchers.everyItem;
import static org.hamcrest.Matchers.greaterThan;

// Проверяем, присутствует ли в списке число 2 и каждый элемент больше нуля, ведь мы за позитивное мышление
assertThat(Arrays.asList(1, 2, 3), allOf(hasItem(2), everyItem(greaterThan(0))));

Матчеры свойств — незаслуженно обделённые вниманием герои

Для сравнения свойств объектов в коллекциях используйте hasProperty:

Java
Скопировать код
import static org.hamcrest.Matchers.hasItem;
import static org.hamcrest.Matchers.hasProperty;

List<Person> persons = Arrays.asList(new Person("Джон", 30), new Person("Джейн", 25));
assertThat(persons, hasItem(hasProperty("name", is("Джейн")))); // Нашли Джейн.

Не забудьте импортировать org.hamcrest.Matchers.is.

Внимание к деталям

Преобразование списков в массивы для удобства сравнения

Если удобнее сравнивать элементы после их преобразования из списка в массив, сделайте следующее:

Java
Скопировать код
String[] expectedArray = {"яблоко", "банан"};
List<String> actualList = Arrays.asList("банан", "яблоко");
assertThat(actualList, containsInAnyOrder(expectedArray)); // снова фрукты, теперь в виде массива!

Избегаем подводных камней!

Соблюдая типобезопасность и правильное использование matchers, вы избавляетесь от странных, но сложных в устранении ошибок.

Читаемые утверждения: все под контролем.

Чтобы ваши утверждения были максимально понятными, проведите статический импорт containsInAnyOrder.

Полезные материалы

  1. Java Hamcrest — официальная документация Hamcrest.
  2. Руководство пользователя JUnit 5 — всё, что нужно знать о тестировании в JUnit 5.
  3. AssertJ – библиотека "плавных" утверждений java — библиотека утверждений AssertJ, альтернатива Hamcrest.
  4. Matchers (Hamcrest)официальная Javadoc для класса Matcher.
  5. GitHub – hamcrest/JavaHamcrest — исходный код и примеры Hamcrest matchers.
  6. Использование Hamcrest для тестирования – учебное пособие — учебное руководство по работе с Hamcrest в тестах JUnit.
Проверь как ты усвоил материалы статьи
Пройди тест и узнай насколько ты лучше других читателей
Какой метод в Hamcrest используется для проверки наличия идентичных элементов в коллекциях, не принимая во внимание их порядок?
1 / 5