AssertEquals 2 Lists ignore order
我认为那应该是一个非常简单的问题。 但是不知何故我无法在Google中找到答案。
假设我有2个字符串列表。 第一个包含"字符串A"和"字符串B",第二个包含"字符串B"和"字符串A"(注意顺序不同)。 我想用JUnit测试它们,以检查它们是否包含完全相同的字符串。
是否有任何断言可以检查忽略顺序的字符串是否相等? 对于给定的示例,org.junit.Assert.assertEquals抛出AssertionError
解决方法是先对列表进行排序,然后再将它们传递给断言。 但是我希望我的代码尽可能简单和干净。
我使用Hamcrest 1.3,JUnit 4.11,Mockito 1.9.5。
正如您提到使用Hamcrest一样,我会选择Matchers之一
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | 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与JUnit的assertTrue一起使用,以检查第一个列表是否包含第二个列表中的每个元素,反之亦然。
1 2 | assertTrue(first.size() == second.size() && first.containsAll(second) && second.containsAll(first)); |
这是一种避免二次复杂性的解决方案(多次遍历列表)。这使用Apache Commons CollectionUtils类来创建每个项目的映射,以将其映射到列表中的频率计数本身。然后,它仅比较两个Map。
1 2 3 | 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
1 2 3 |
我参加聚会晚了,但这是我仅使用Junit的解决方案。任何想法都欢迎。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | 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); } |
您可以使用junit-addons jar中附带的ListAssert。
1 |
请注意,Roberto Izquierdo的解决方案通常具有二次复杂度。 HashSets上的解决方案始终具有线性复杂度:
使用AssertJ,您需要
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | 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"); } } |
为了快速解决问题,我将同时检查两种方法:
1 2 | assertTrue(first.containsAll(second)); assertTrue(second.containsAll(first)); |
并尝试在相同元素的数量不同的情况下(例如1、1、2和1、2、2),我没有得到误报。