Подтвердить что ты не робот

Как утверждать, что Iterable содержит элементы с определенным свойством?

Предположим, что я хочу unit test метод с этой сигнатурой:

List<MyItem> getMyItems();

Предположим, что MyItem - это Pojo, обладающее многими свойствами, один из которых "name", доступ через getName().

Все, что мне нужно для проверки, состоит в том, что List<MyItem> или любой Iterable содержит два экземпляра MyItem, чьи свойства "name" имеют значения "foo" и "bar". Если какие-либо другие свойства не совпадают, мне совершенно не нужны цели этого теста. Если имена совпадают, это успешный тест.

Я хотел бы, чтобы это было однострочным, если возможно. Вот какой-то "псевдо-синтаксис" того, что я хотел бы сделать.

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

Может ли Хэмкрест быть хорошим для такого рода вещей? Если да, то какова будет именно версия hamcrest моего псевдосинтакса выше?

4b9b3361

Ответ 1

Спасибо @Разван, который указал мне в правильном направлении. Я смог получить его в одной строке, и я успешно охотился на импорт для 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

Try:

assertThat(myClass.getMyItems(),
                          hasItem(hasProperty("YourProperty", is("YourValue"))));

Ответ 3

Это не особенно Хамкрест, но я думаю, стоит упомянуть здесь. То, что я использую довольно часто в Java8, выглядит примерно так:

assertTrue(myClass.getMyItems().stream().anyMatch(item -> "foo".equals(item.getName())));

(Отредактировано для небольшого улучшения Родриго Маньяри. Это немного меньше подробностей. См. комментарии.)

Это может быть немного труднее читать, но мне нравится тип и рефакторинг безопасности. Он также отлично подходит для тестирования нескольких свойств bean в комбинации. например с java-like && выражение в лямбда фильтра.

Ответ 4

Assertj хорош в этом.

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

    assertThat(myClass.getMyItems()).extracting("name").contains("foo", "bar");

Большой плюс для assertj по сравнению с hamcrest - это простое использование кода.

Ответ 5

AssertJ предоставляет отличную функцию в 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"); 

В качестве примечания: чтобы утверждать несколько полей из элементов List, с помощью AssertJ мы делаем это, помещая ожидаемые значения для каждого элемента в функцию tuple():

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

Ответ 6

Пока ваш список является конкретным классом, вы можете просто вызвать метод contains(), если вы внедрили метод equals() в MyItem.

// 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")));

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