Как утверждать, что два списка ‹String› равны, игнорируя порядок

Я использую AssertJ и пытаюсь утверждать, что два List<String> содержат одинаковые строки, игнорируя порядок .

List<String> expected = Arrays.asList("Something-6144-77.pdf", "d-6144-77.pdf", "something-6144-78.pdf", "Something-6144-8068.pdf");
List<String> actual = new ArrayList<String>();

assertThat(actual.size()).isEqualTo(expected.size());

// This line gives the error: "The method containsExactlyInAnyOrder(String...) in the type ListAssert<String> is not applicable for the arguments (List<String>)"
assertThat(actual).containsExactlyInAnyOrder(expected);

Как я могу исправить приведенную ниже ошибку компиляции, которая появляется при попытке использовать containsExactlyInAnyOrder()?

«Метод containsExactlyInAnyOrder (String ...) в типе ListAssert не применим для аргументов (List)»


person Catfish    schedule 27.03.2017    source источник


Ответы (4)


Сообщение об ошибке дает вам решение:

The method containsExactlyInAnyOrder(String...)

String... - любое количество строк, но может также передаваться как массив:

assertThat(actual).containsExactlyInAnyOrder((String[]) expected.toArray(new String[expected.size()]));

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

Вот некоторая документация по varargs (произвольное количество аргументов, ...): https://docs.oracle.com/javase/tutorial/java/javaOO/arguments.html

person jlordo    schedule 27.03.2017

Оба ответа (от jlordo и by dasblinkenlight) работают, но представляют собой обходные пути, а не правильный способ сделать это.

В библиотеке AssertJ есть метод для конкретной проверки того, содержит ли List все значения, независимо от порядка, в другом Iterable. Он называется _ 3_:

public SELF containsOnlyElementsOf(Iterable<? extends ELEMENT> iterable)

Та же семантика, что и у ObjectEnumerableAssert.containsOnly(Object[]): проверяет, что фактический объект содержит все элементы данной итерации и ничего больше в любом порядке.

Пример:

Iterable<Ring> rings = newArrayList(nenya, vilya);

// assertion will pass
assertThat(rings).containsOnlyElementsOf(newLinkedList(nenya, vilya)) .containsOnlyElementsOf(newLinkedList(nenya, nenya, vilya, vilya));

// assertion will fail as actual does not contain narya
assertThat(rings).containsOnlyElementsOf(newLinkedList(nenya, vilya, narya));
// assertion will fail as actual contains nenya assertThat(rings).containsOnlyElementsOf(newLinkedList(vilya));

Итак, вам следует использовать этот метод, как показано ниже. Нет необходимости преобразовывать ваш List в Array.

assertThat(actual).containsOnlyElementsOf(expected);

В качестве примечания, ваше утверждение о размере списка является избыточным:

assertThat(actual.size()).isEqualTo(expected.size());

Об этом уже говорится в утверждении, что списки содержат одни и те же элементы.

Наконец, если вам нужно подтвердить, что в списке есть конкретный сайт, AssertJ имеет для этого встроенный метод (_ 17_):

assertThat(actual).hasSameSizeAs(expected);
person Magnilex    schedule 29.05.2017

Поскольку метод принимает String..., вы должны передать массив вместо списка:

String[] expected = new String[] {
    "Something-6144-77.pdf"
,   "d-6144-77.pdf"
,   "something-6144-78.pdf"
,   "Something-6144-8068.pdf"
};

или вызовите его со встроенным списком элементов:

assertThat(actual).containsExactlyInAnyOrder(
    "Something-6144-77.pdf"
,   "d-6144-77.pdf"
,   "something-6144-78.pdf"
,   "Something-6144-8068.pdf"
);
person Sergey Kalinichenko    schedule 27.03.2017

В более новых версиях assertj есть содержитExactlyInAnyOrderElements именно для этой цели. . Ваш пример сводится к

assertThat(actual).containsExactlyInAnyOrderElementsOf(expected);
person dastrobu    schedule 29.10.2019