it-roy-ru.com

AssertEquals 2 Списки игнорируют порядок

Это должен быть действительно простой вопрос, я верю. Но почему-то я не могу найти ответ в Google.

Предположим, что у меня есть 2 списка строк. Первый содержит "String A" и "String B", второй содержит "String B" и "String A" (заметьте разницу в порядке). Я хочу проверить их с помощью JUnit, чтобы проверить, содержат ли они точно такие же строки.

Есть ли утверждение, которое проверяет равенство строк, которые игнорируют порядок? Для данного примера org.junit.Assert.assertEquals выбрасывает AssertionError 

Java.lang.AssertionError: expected:<[String A, String B]> but was:<[String B, String A]>

Обходной путь - сначала отсортировать списки, а затем передать их утверждению. Но я хочу, чтобы мой код был максимально простым и понятным.

Я использую Hamcrest 1.3, JUnit 4.11, Mockito 1.9.5.

54
kukis

Поскольку вы упоминаете, что вы используете Hamcrest, я бы выбрал один из коллекции Matchers

import static org.hamcrest.collection.IsIterableContainingInAnyOrder.containsInAnyOrder;
import static org.junit.Assert.assertThat;

public class CompareListTest {

    @Test
    public void compareList() {
        List<String> expected = Arrays.asList("String A", "String B");
        List<String> actual = Arrays.asList("String B", "String A");

        assertThat("List equality without order", 
            actual, containsInAnyOrder(expected.toArray()));
    }

}
54
cheffe

Вы можете использовать List.containsAll с assertTrue JUnit, чтобы проверить, что первый список содержит каждый элемент из второго, и наоборот.

assertTrue(first.size() == second.size() && 
    first.containsAll(second) && second.containsAll(first));
45
robertoia

Вот решение, которое позволяет избежать квадратичной сложности (многократное повторение списков). При этом используется класс Apache Commons CollectionUtils для создания карты каждого элемента по частоте в списке. Затем он просто сравнивает две карты. 

Assert.assertEquals("Verify same metrics series",
    CollectionUtils.getCardinalityMap(expectedSeriesList),
    CollectionUtils.getCardinalityMap(actualSeriesList));

Я также только что заметил CollectionUtils.isEqualCollection, который утверждает, что делает именно то, что запрашивается здесь ...

https://commons.Apache.org/proper/commons-collections/apidocs/index.html?org/Apache/commons/collections4/CollectionUtils.html

7
Alex Worden

Отметим, что решение Роберто Изкиердо в целом имеет квадратичную сложность. Решение на HashSets всегда имеет линейную сложность:

assertTrue(first.size() == second.size() &&
        new HashSet(first).equals(new HashSet(second)));
1
leventov

Вы можете использовать ListAssert , который поставляется в банке junt-addons.

ListAssert.assertEquals(yourList, Arrays.asList(3, 4, 5));
1
Akash

Я опоздал на вечеринку, но вот мое решение с использованием только Junit. Любые мысли приветствуются. 

List<String> actual = new ArrayList<>();
actual.add("A");
actual.add("A");
actual.add("B");

List<String> expected = new ArrayList<>();
actual.add("A");
actual.add("B");
actual.add("B");

//Step 1: assert for size
assertEquals(actual.size(), expected.size());

//Step 2: Iterate
for(String e: expected){
    assertTrue(actual.contains(e));
    actual.remove(e);
}
0
Sujit Joshi

Для быстрого исправления я бы проверил оба способа:

assertTrue(first.containsAll(second));
assertTrue(second.containsAll(first));

И пытаясь с ситуацией, когда число одинаковых элементов различно (например, 1, 1, 2 и 1, 2, 2), я не получил ложных срабатываний.

0
Kristjan Veskimäe