AssertEquals 2列表忽略顺序

kuk*_*kis 65 java arrays junit unit-testing assertion

我认为这应该是一个非常简单的问题.但不知何故,我无法在谷歌找到答案.

假设我有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]>
Run Code Online (Sandbox Code Playgroud)

解决方法是首先对列表进行排序,然后将它们传递给断言.但我希望我的代码尽可能简单和干净.

我使用Hamcrest 1.3,JUnit 4.11,Mockito 1.9.5.

che*_*ffe 65

当你提到你使用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()));
    }

}
Run Code Online (Sandbox Code Playgroud)

  • 另请参阅我的答案http://stackoverflow.com/a/38262680/297710,其中显示了如何改进Hamcrest匹配器并避免使用containsInAnyOrder在每个断言中使用".toArray()" (5认同)

rob*_*oia 47

您可以将List.containsAll与JUnit的assertTrue一起使用来检查第一个列表是否包含第二个列表中的每个元素,反之亦然.

assertTrue(first.size() == second.size() && 
    first.containsAll(second) && second.containsAll(first));
Run Code Online (Sandbox Code Playgroud)

  • 这不适用于列表中的重复项.下面是一个演示示例:`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提到了Apache Commons Collections的CollectionUtils.isEqualCollection(),对于这个例子,它正确地检测到集合不相等. (10认同)
  • 这个答案和我的一样不正确. (4认同)
  • 当然是.2给定列表必须完全相同,只是忽略顺序. (4认同)
  • @kukis这取决于,你想检查重复吗? (2认同)
  • @kukis然后检查ZouZou对你的问题的评论. (2认同)

Ale*_*den 10

这是一个避免二次复杂度的解决方案(多次迭代列表).这使用Apache Commons CollectionUtils类在列表中创建每个项目的Map到频率计数本身.然后它只是比较两个地图.

Assert.assertEquals("Verify same metrics series",
    CollectionUtils.getCardinalityMap(expectedSeriesList),
    CollectionUtils.getCardinalityMap(actualSeriesList));
Run Code Online (Sandbox Code Playgroud)

我也刚刚发现了CollectionUtils.isEqualCollection声称完全按照这里要求做的...

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


dav*_*xxx 7

使用 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");
    }    
}
Run Code Online (Sandbox Code Playgroud)


Tin*_*ool 6

    Collections.sort(excepted);
    Collections.sort(actual);
    assertEquals(excepted,actual);
Run Code Online (Sandbox Code Playgroud)