Hamcrest порівнюють колекції


114

Я намагаюся порівняти 2 списки:

assertThat(actual.getList(), is(Matchers.containsInAnyOrder(expectedList)));

Але ідея

java: no suitable method found for assertThat(java.util.List<Agent>,org.hamcrest.Matcher<java.lang.Iterable<? extends model.Agents>>)
method org.junit.Assert.<T>assertThat(T,org.hamcrest.Matcher<T>) is not applicable
  (no instance(s) of type variable(s) T exist so that argument type org.hamcrest.Matcher<java.lang.Iterable<? extends model.Agents>> conforms to formal parameter type org.hamcrest.Matcher<T>)
method org.junit.Assert.<T>assertThat(java.lang.String,T,org.hamcrest.Matcher<T>) is not applicable
  (cannot instantiate from arguments because actual and formal argument lists differ in length)

Як мені це написати?

Відповіді:


161

Якщо ви хочете стверджувати, що два списки однакові, не ускладнюйте речі Hamcrest:

assertEquals(expectedList, actual.getList());

Якщо ви дійсно маєте намір здійснити порівняння, що не containsInAnyOrderвраховує порядок, ви можете зателефонувати за методом varargs та вказати значення безпосередньо:

assertThat(actual.getList(), containsInAnyOrder("item1", "item2"));

(Якщо припустити, що ваш список є String, а не Agentдля цього прикладу.)

Якщо ви дійсно хочете викликати той самий метод із вмістом List:

assertThat(actual.getList(), containsInAnyOrder(expectedList.toArray(new String[expectedList.size()]));

Без цього ви викликаєте метод одним аргументом і створюєте Matcherте, що очікує, що відповідатиме тому, Iterableде кожен елемент є List. Це неможливо використати для відповідності List.

Тобто ви не можете співставити зі List<Agent>знаком a Matcher<Iterable<List<Agent>>, саме це намагається ваш код.


+1 для "Якщо ви дійсно хочете викликати той самий метод із вмістом списку". На жаль, я не міг цього вирішити сам. Особливо, що є конструктор, який бере колекцію.
Ейяд Ебрагім

3
@Tim Не зовсім; containsInAnyOrderвимагає, щоб були присутні всі елементи, щоб перше твердження вийшло з ладу. Подивіться, hasItemsчи хочете ви перевірити наявність принаймні цих елементів.
Джо

4
Якщо ви використовуєте содержаInAnyOrder, спочатку переконайтесь, що обидва списки мають однаковий розмір ... Якщо actual.getList()трапляється "item1", "item3", "item2", тест пройде і, можливо, ви хочете переконатися, що він містить лише перелічені елементи ... У цьому випадку ви можете використовувати assertThat(actual.getList().size(), equalTo(2));перед тим, що міститьInInnyOrder, таким чином ви переконайтеся, що обидва списки мають однаковий вміст.
Мартін

1
@Martin ти думаєш hasItems. Додаткова перевірка тут непотрібна. Дивіться коментар до Тима вище, а також як відрізняються Хатереси Хамресту, містять і міститьInAnyOrder?
Джо

1
Користувачі Kotlin : не забудьте додати оператор розповсюдження ( *expectedList.toTypedArray()), передаючи масив як varargs!
Джеймс Боуман

63
List<Long> actual = Arrays.asList(1L, 2L);
List<Long> expected = Arrays.asList(2L, 1L);
assertThat(actual, containsInAnyOrder(expected.toArray()));

Коротша версія відповіді @ Joe без зайвих параметрів.


28

Щоб доповнити відповідь @ Joe:

Hamcrest надає три основні способи відповідності списку:

contains Перевіряє відповідність усіх елементів, враховуючи порядок, якщо в списку є більше або менше елементів, він не вдасться

containsInAnyOrder Перевіряє відповідність усіх елементів, і не має значення порядок, якщо список містить більш-менш елементів, не вдасться

hasItems Перевіряє лише вказані об'єкти, не має значення, чи є в списку більше

hasItem Перевіряє лише один об'єкт, не важливо, чи в списку більше

Усі вони можуть отримувати список об'єктів і використовувати equalsметод порівняння або можуть бути змішані з іншими математиками, такими як згаданий @borjab:

assertThat(myList , contains(allOf(hasProperty("id", is(7L)), 
                                   hasProperty("name", is("testName1")),
                                   hasProperty("description", is("testDesc1"))),
                             allOf(hasProperty("id", is(11L)), 
                                   hasProperty("name", is("testName2")),
                                   hasProperty("description", is("testDesc2")))));

http://hamcrest.org/JavaHamcrest/javadoc/1.3/org/hamcrest/Matchers.html#contains (E ...) http://hamcrest.org/JavaHamcrest/javadoc/1.3/org/hamcrest/Matchers.html #containsInAnyOrder (java.util.Collection) http://hamcrest.org/JavaHamcrest/javadoc/1.3/org/hamcrest/Matchers.html#hasItems (T ...)


Трохи запізнюємось на вечірку, але дякую за опис відмінностей між кожним методом.
Маркос де Андраде

Чудове рішення у випадку, якщо елементи списку справ не є примітивними.
Станіслав

Чи існує безпечний тип цього способу?
andresp

15

З існуючими бібліотеками Hamcrest (станом на v.2.0.0.0) ви змушені використовувати метод Collection.toArray () у вашій колекції, щоб використовувати містити InAnyOrder Matcher. Набагато приємніше було б додати це як окремий метод до org.hamcrest.Matchers:

public static <T> org.hamcrest.Matcher<java.lang.Iterable<? extends T>> containsInAnyOrder(Collection<T> items) {
    return org.hamcrest.collection.IsIterableContainingInAnyOrder.<T>containsInAnyOrder((T[]) items.toArray());
}

Насправді я доповнив цей метод у моїй користувальницькій бібліотеці тестів і використовую його для підвищення читабельності моїх тестових випадків (через меншу багатослівність).


2
Гарний, я буду використовувати цей помічник. Повідомлення про затвердження тут є більш інформативним: воно називає відсутні пункти по одному, а не просто: список має бути elem1, elem2, .. elem99, але я отримав elem1, elem2, ..., elem98 - удача знаходження зниклого.
pihentagy

3

Переконайтеся, що Objects у вашому списку equals()визначено. Тоді

    assertThat(generatedList,is(equalTo(expectedList)));

працює.


1

Для переліку об’єктів вам може знадобитися щось подібне:

import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.contains;
import static org.hamcrest.Matchers.allOf;
import static org.hamcrest.beans.HasPropertyWithValue.hasProperty;
import static org.hamcrest.Matchers.is;

@Test
@SuppressWarnings("unchecked")
public void test_returnsList(){

    arrange();
  
    List<MyBean> myList = act();
    
    assertThat(myList , contains(allOf(hasProperty("id",          is(7L)), 
                                       hasProperty("name",        is("testName1")),
                                       hasProperty("description", is("testDesc1"))),
                                 allOf(hasProperty("id",          is(11L)), 
                                       hasProperty("name",        is("testName2")),
                                       hasProperty("description", is("testDesc2")))));
}

Використовуйте містити InInnyOrder, якщо ви не хочете перевіряти порядок об'єктів.

PS Будь-яка допомога, щоб уникнути поданого попередження, буде дуже вдячна.


-3

Щоб порівняти два списки із порядком збереженого порядку,

assertThat(actualList, contains("item1","item2"));

Це не дає відповіді на запитання.
kamczak

Частково це і є.
rvazquezglez

@rvazquezglez Що ти маєш на увазі? Чому ти це кажеш? Результат методу є правильним у моєму середовищі.
niaomingjian

@niaomingjian Код перевіряє, чи actualListмістять елементи всередині containsматчера, що не вдасться, якщо елементи не в тому ж порядку, а також вийде з ладу, якщо він містить більше елементів або відсутній.
rvazquezglez

@rvazquezglez, тому мета коду - вивчити точну рівність (однакові довжини, значення та порядок) у двох списках, правда?
niaomingjian
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.