Я считаю, что это должен быть действительно простой вопрос. Но как-то не могу найти ответ в гугле.
Предположим, у меня есть 2 списка строк. Первый содержит «Строку A» и «Строку B» , второй - «Строку B» и «Строку 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 .
list1.removeAll(list2)
следует оставитьlist1
пустым. Я думаю, вы можете использовать это, чтобы получить то, что хотите.containsAll
иremoveAll
предназначеныO(n²)
для списков при их сортировке, а проверка на равенство -O(nlogn)
.Collections.sort(list1); Collections.sort(list2); assertTrue(list1.equals(list2));
тоже чистый.Ответы:
Когда вы упомянули, что используете 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())); } }
источник
Вы можете использовать List.containsAll с assertTrue JUnit, чтобы проверить, что первый список содержит все элементы из второго, и наоборот.
источник
assertEquals(first.size(), second.size())
.. тогда он должен работать, как ожидалосьList<String> list1 = Arrays.asList("a", "a", "b");
List<String> list2 = Arrays.asList("a", "b", "b");
assertEquals(list1.size(), list2.size());
assertTrue(list1.containsAll(list2) && list2.containsAll(list1));
в этом примере оба утверждения не могут определить, что списки на самом деле разные. @AlexWorden упоминает CollectionUtils.isEqualCollection () Apache Commons Collections, которая в этом примере правильно определяет, что коллекции не равны.Вот решение, которое позволяет избежать квадратичной сложности (повторение списков несколько раз). При этом используется класс 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
источник
С AssertJ
containsExactlyInAnyOrder()
илиcontainsExactlyInAnyOrderElementsOf()
то, что вам нужно:import org.assertj.core.api.Assertions; import org.junit.jupiter.api.Test; import java.util.Arrays; import java.util.List; public class CompareListTest { @Test public void compareListWithTwoVariables() { List<String> expected = Arrays.asList("String A", "String B"); List<String> actual = Arrays.asList("String B", "String A"); Assertions.assertThat(actual) .containsExactlyInAnyOrderElementsOf(expected); } @Test public void compareListWithInlineExpectedValues() { List<String> actual = Arrays.asList("String B", "String A"); Assertions.assertThat(actual) .containsExactlyInAnyOrder("String A", "String B"); } }
источник
источник
Я опаздываю на вечеринку, но вот мое решение, использующее только 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); }
источник
Обратите внимание, что решение Роберто Искьердо в целом имеет квадратичную сложность. Решение на HashSets всегда имеет линейную сложность:
assertTrue(first.size() == second.size() && new HashSet(first).equals(new HashSet(second)));
источник
("s1", "s2", "s3" ,"s1")
и второе -("s2", "s1", "s3" ,"s2");
это разные списки.Для быстрого исправления я бы проверил оба способа:
И попробовав в ситуации, когда количество одинаковых элементов разное (например, 1, 1, 2 и 1, 2, 2), я не получил ложных срабатываний.
источник
Вы можете использовать ListAssert, который поставляется в jar-файле junit-addons.
ListAssert.assertEquals(yourList, Arrays.asList(3, 4, 5));
источник
Похоже, что другие ответы либо ссылаются на сторонние утилиты, либо неверны, либо неэффективны.
Вот ванильное решение O (N) в Java 8.
public static void assertContainsSame(Collection<?> expected, Collection<?> actual) { assert expected.size() == actual.size(); Map<Object, Long> counts = expected.stream() .collect(Collectors.groupingBy( item -> item, Collectors.counting())); for (Object item : actual) assert counts.merge(item, -1L, Long::sum) != -1L; }
источник