Java AssertEquals 2 列表忽略顺序

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/22807328/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-13 18:02:43  来源:igfitidea点击:

AssertEquals 2 Lists ignore order

javaarraysunit-testingjunitassertion

提问by kukis

That should be really simple question I believe. But somehow I can't find answer in Google.

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

Assume that I have 2 Lists of Strings. First contains "String A" and "String B", second one contains "String B" and "String A"(notice difference in order). I want to test them with JUnitto check whether they contains exactly the sameStrings.

假设我有 2 个字符串列表。第一个包含"String A" 和 "String B",第二个包含"String B" 和 "String A"(注意顺序不同)。我想用JUnit测试它们以检查它们是否包含完全相同的字符串。

Is there any assert that checks equality of Strings that ignore order? For given example org.junit.Assert.assertEquals throws AssertionError

是否有任何断言检查忽略顺序的字符串的相等性?对于给定的示例 org.junit.Assert.assertEquals 抛出 AssertionError

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

Work around is to sort Lists firstly and then pass them to assertion. But I want my code to be as simple and clean as possible.

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

I use Hamcrest 1.3, JUnit 4.11, Mockito 1.9.5.

我使用Hamcrest 1.3JUnit 4.11Mockito 1.9.5

采纳答案by cheffe

As you mention that you use Hamcrest, I would pick one of the collection Matchers

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

}

回答by robertoia

You can use List.containsAllwith JUnit's assertTrue to check that the first list contains every element from the second one, and vice versa.

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

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

回答by Kristjan Veskim?e

For a quick fix I would check both ways:

为了快速修复,我会检查两种方式:

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

And trying with a situation where the number of the same elements is different (e.g. 1, 1, 2 and 1, 2, 2) I didn't get false positives.

并尝试在相同元素的数量不同的情况下(例如 1, 1, 2 和 1, 2, 2)我没有得到误报。

回答by leventov

Note that solution by Roberto Izquierdo has quadratic complexity in general. Solution on HashSets always has linear complexity:

请注意,Roberto Izquierdo 的解决方案通常具有二次复杂性。HashSets 上的解决方案总是具有线性复杂度:

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

回答by akungta

You can use ListAssertthat comes in junit-addons jar.

您可以使用junit-addons jar 中的ListAssert

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

回答by Alex Worden

Here's a solution that avoids quadratic complexity (iterating over the lists multiple times). This uses the Apache Commons CollectionUtils class to create a Map of each item to a frequency count itself in the list. It then simply compares the two Maps.

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

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

I also just spotted CollectionUtils.isEqualCollection that claims to do exactly what is being requested here...

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

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

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

回答by Sujit Joshi

Im late to the party but here's my solution using Junit only. Any thoughts are welcome.

我迟到了,但这是我仅使用 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);
}

回答by Tinyfool

    Collections.sort(excepted);
    Collections.sort(actual);
    assertEquals(excepted,actual);

回答by davidxxx

With AssertJ, containsExactlyInAnyOrder()or containsExactlyInAnyOrderElementsOf()is what you need :

使用 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");
    }    
}

回答by Daniel Avery

Looks like the other answers either reference 3rd party utils, are incorrect, or are inefficient.

看起来其他答案要么参考了 3rd 方实用程序,要么不正确,要么效率低下。

Here's a O(N) vanilla solution in Java 8.

这是 Java 8 中的 O(N) vanilla 解决方案。

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;
}