programing

AssertEquals 2 리스트는 순서를 무시합니다.

shortcode 2022. 9. 22. 23:59
반응형

AssertEquals 2 리스트는 순서를 무시합니다.

그건 정말 간단한 질문일 겁니다.그런데 구글에서 답을 찾을 수가 없어요.

문자열 목록이 2개 있다고 가정합니다.첫 번째는 "String A"와 "String B"를 포함하며, 두 번째는 "String B"와 "String A"를 포함합니다(순서의 차이를 알 수 있습니다).JUnit으로 테스트하여 동일한 Strings가 포함되어 있는지 확인하고 싶습니다.

순서를 무시하는 문자열의 동일성을 체크하는 어설션이 있습니까?예를 들어 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사용합니다.

당신이 햄크레스트를 사용한다고 했듯이
그래서 나는 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.contains사용할 수 있습니다.모두 JUnit의 주장으로첫 번째 목록에 두 번째 목록의 모든 요소가 포함되어 있는지 또는 두 번째 목록의 모든 요소가 포함되어 있는지 확인할 수 있습니다.

assertEquals(expectedList.size(), actualList.size());
assertTrue(expectedList.containsAll(actualList));
assertTrue(actualList.containsAll(expectedList));

힌트:
목록에 있는 중복 항목에서는 작동하지 않습니다.

2차 복잡성(목록에서 여러 번 반복)을 회피하는 솔루션이 있습니다.Apache Commons Collection Utils 클래스를 사용하여 목록의 빈도 수에 대한 각 항목의 맵을 만듭니다.그런 다음 단순히 두 맵을 비교합니다.

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

Collection Utils.Equal Collection도 여기서 요구하는 것을 정확히 수행하고 있습니다.

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");
    }    
}
    Collections.sort(excepted);
    Collections.sort(actual);
    assertEquals(excepted,actual);

파티에 늦었지만 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);
}

빠른 수정을 위해 두 가지 방법을 모두 확인합니다.

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

또, 같은 요소의 수가 다른 상황(예: 1, 1, 2, 2)에서는, false positive를 얻을 수 없었습니다.

junit-addons jar에 포함된 ListAssert를 사용할 수 있습니다.

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

Roberto Izquierdo의 해는 일반적으로 2차 복잡도를 가집니다.HashSets의 솔루션에는 항상 선형 복잡성이 있습니다.

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

다른 답변은 서드파티제의 유틸리티를 참조하고 있거나 올바르지 않거나 비효율적인 것 같습니다.

Java 8의 O(N) 바닐라 솔루션을 소개합니다.

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

언급URL : https://stackoverflow.com/questions/22807328/assertequals-2-lists-ignore-order

반응형