JUnit 4 비교 세트


102

Collection요소, 특히 SetJUnit 4 의 동등성을 어떻게 간결하게 주장 할 수 있습니까?



두 세트가 서로 같거나 (동일한 요소를 포함 함) 동일한 세트의 두 요소가 동일하다고 주장하려고합니까?
Bill the Lizard

두 세트의 요소가 같은지 확인해야합니다
Eqbal

답변:


103

Sets가 서로 동일하다고 주장 하여 Set equals()메서드 를 호출 할 있습니다.

public class SimpleTest {

    private Set<String> setA;
    private Set<String> setB;

    @Before
    public void setUp() {
        setA = new HashSet<String>();
        setA.add("Testing...");
        setB = new HashSet<String>();
        setB.add("Testing...");
    }

    @Test
    public void testEqualSets() {
        assertEquals( setA, setB );
    }
}

@Test두 경우에 합격 Set(S)가 동일한 크기 및 동일한 구성 요소를 포함한다.


7
이것은 보고서에 아주 좋은 결과를 표시하지 않습니다. toStrings가 명확하게 정의 된 경우 더 좋지만 여전히 좋지 않습니다 (작은 차이가 텍스트 페이지로 끝날 수 있음)
Bill K

음, 어떻게 왔는지 : java.lang.AssertionError : expected : java.util.Hashtable <{CompanyName = 8PKQ9va3nW8pRWb4SjPF2DvdQDBmlZ, Ric = sZwmXAdYKv, Category = AvrIfd, QuoteId = 4342740204922826921}>하지만 : java.utild, QuoteId = 4342740 {CompanyName.Hashtable = 8PKQ9va3nW8pRWb4SjPF2DvdQDBmlZ, 릭 = sZwmXAdYKv, 종류 = AvrIfd, QuoteId = 4342740204922826921}>
조반니 보타

3
@Giodude Hashtable에 저장하는 클래스 가 equals있고 hashCode구현 되었습니까?
Bill the Lizard

보시다시피 그것들은 단지 문자열이고 긴 것입니다. 저는 Avro를 테스트하여 맵을 직렬화 및 역 직렬화하고 있으며 그 결과입니다. 문자열이 직렬화되고 직렬화 해제되어 테스트가 실패하는 방식에 문제가 있다고 생각하지만 문제를 찾을 수없는 것 같습니다.
Giovanni Botta 2013 년

두 개의 HashSet <Long>을 비교하더라도 나를 위해 작동하지 않았습니다. @MattFriedman 답변은 실제로 내 사용 사례에서 작동합니다.
bluecollarcoder 2014

46

아파치 커먼즈를 다시 구출하십시오.

assertTrue(CollectionUtils.isEqualCollection(coll1, coll2));

매력처럼 작동합니다. 이유는 모르겠지만 컬렉션에서 다음 assertEquals(coll1, coll2)이 항상 작동하는 것은 아닙니다. 나에게 실패한 경우에는 Sets가 지원하는 두 개의 컬렉션이 있습니다. hamcrest와 junit은 내가 확실히 알았음에도 불구하고 컬렉션이 동등하다고 말하지 않았습니다. CollectionUtils를 사용하면 완벽하게 작동합니다.


20
이것은 실제로 사소한, 까다로운 부분은 호출자에게 차이를 나타냅니다 명확하게하는 것입니다
빌 K

1
받아 들여지는 대답은 원래 질문 (특히 두 세트에 대한 단위 테스트)에 대한 좋은 대답이지만 CollectionUtils 의이 대답은 가장 일반적인 경우에 더 나은 대답이라고 생각합니다. CollectionUtils를 사용하지 않으면 Collection과 Set을 비교할 수 없었습니다.
제이

16

hamcrest :

assertThat(s1, is(s2));

평범한 주장으로 :

assertEquals(s1, s2);

NB : t 구체적인 세트 클래스 의 equals () 메소드 가 사용됩니다.


1
Hamcrest는 JUnit 4와 함께 제공되므로 다른 라이브러리가 필요하지 않으므로이 방법을 선호합니다.
JRSofty

2
세트의 유형이 다른 경우 작동하지 않을 수 있습니다.
Hans-Peter Störr

7

특히 흥미로운 경우는

   java.util.Arrays$ArrayList<[[name,value,type], [name1,value1,type1]]> 

   java.util.Collections$UnmodifiableCollection<[[name,value,type], [name1,value1,type1]]>

지금까지 내가 본 유일한 해결책은 둘 다 세트로 변경하는 것입니다.

assertEquals(new HashSet<CustomAttribute>(customAttributes), new HashSet<CustomAttribute>(result.getCustomAttributes()));

또는 요소별로 비교할 수 있습니다.


실제로 다른 답변에 제시된 몇 가지 솔루션이 있습니다. 어쨌든 세트는 순서를 무시하기 때문에 약간 불행합니다. 아마도 ArrayList?
Hans-Peter Störr

4

배열 기반의 추가 방법으로 ... junitx에서 정렬되지 않은 배열 어설 션 사용을 고려할 수 있습니다. Apache CollectionUtils 예제가 작동하지만 여기에도 견고한 어설 션 확장 패키지가 있습니다.

나는

ArrayAssert.assertEquivalenceArrays(new Integer[]{1,2,3}, new Integer[]{1,3,2});

접근 방식은 훨씬 더 읽기 쉽고 디버깅이 가능할 것입니다 (모든 컬렉션은 toArray ()를 지원하므로 ArrayAssert 메서드를 사용하는 것이 충분히 쉬워야합니다.

물론 여기서 단점은 junitx가 추가 jar 파일 또는 maven 항목이라는 것입니다.

 <dependency org="junit-addons" name="junit-addons" rev="1.4"/>

2

이 기사를 확인 하십시오 . 한 가지 예 :

@Test  
public void listEquality() {  
    List<Integer> expected = new ArrayList<Integer>();  
    expected.add(5);  

    List<Integer> actual = new ArrayList<Integer>();  
    actual.add(5);  

    assertEquals(expected, actual);  
}  

짧지 만 좋은 링크, 당신은 Junit4-로 할 수있는 정말 빨리 설명
요하네스

1
링크가 끊어졌습니다. 온라인에서 보관 된 버전을 찾거나 그 내용을 요약 할 수 있습니까?
pzp

1

Hamcrest 사용 :

assertThat( set1, both(everyItem(isIn(set2))).and(containsInAnyOrder(set1)));

이는 세트의 데이터 유형이 서로 다른 경우에도 작동하며 실패하는 대신 차이를보고합니다.


2
isIn에 대한 가져 오기는 무엇입니까? IntelliJ는 hamcret 패키지로 가져 오기를 해결할 수 없습니다.
fabien

0

List 또는 Set에 특정 값 집합이 포함되어 있는지 확인하려면 (이미 기존 컬렉션과 비교하는 대신) 종종 toString 컬렉션 메서드가 유용합니다.

String[] actualResult = calltestedmethod();
assertEquals("[foo, bar]", Arrays.asList(actualResult).toString());

List otherResult = callothertestedmethod();
assertEquals("[42, mice]", otherResult.toString());

이것은 예상되는 컬렉션을 처음 구성하고 실제 컬렉션과 비교하는 것보다 약간 짧으며 작성하고 수정하기 쉽습니다.

(분명히 이것은 특별히 깨끗한 방법이 아니며 "foo, bar"요소를 "foo"및 "bar"두 요소와 구별 할 수 없습니다. 그러나 실제로 테스트를 작성하는 것이 쉽고 빠르다는 것이 가장 중요하다고 생각합니다. , 그렇지 않으면 많은 개발자가 누르지 않고는 할 수 없습니다.)


이렇게하면 단위 테스트의 결과가 목록의 toString 구현에 따라 달라집니다. 서식을 변경하기로 결정하면 단위 테스트가 더 이상 작동하지 않습니다. 나는 이것이 안전하다고 생각하지 않을 것입니다.
Laurens Op 't Zandt

@ LaurensOp'tZandt Oracle이 Collection.toList ()의 형식을 변경한다는 뜻입니까? 그것은 확실히 일어나지 않을 것입니다. 그러나 특별히 깨끗하지 않은 것은 맞습니다. 그러나 실제로는 테스트를 작성하는 것이 매우 쉽다는 것이 가장 중요하다는 인상을 받았습니다.
Hans-Peter Störr

동의합니다. toString 메서드는 가능성이 없을 것 같습니다. 그래서 아마도 계속 작동 할 것입니다. 나는 그다지 깨끗한 방법이 아니라는 점을 지적하고 싶었습니다. 그러나 실제로는 매우 쉽습니다. 발생하는 한 가지 문제는 세트를 비교할 때입니다. 주문이 보장되지 않기 때문에.
Laurens Op 't Zandt

0

나는 Hans-Peter Störr의 해결책을 좋아합니다. 그러나 그것은 옳지 않다고 생각합니다. 슬프게도 비교할 objetcs를 containsInAnyOrder허용하지 않습니다 Collection. 따라서 다음 CollectionMatcher같아야합니다.

assertThat(set1, containsInAnyOrder(set2.stream().map(IsEqual::equalTo).collect(toList())))

가져 오기는 다음과 같습니다.

import static java.util.stream.Collectors.toList;
import static org.hamcrest.Matchers.containsInAnyOrder;
import static org.junit.Assert.assertThat;
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.