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. 따라서 다음 Collection과 Matcher같아야합니다.

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.