[java] Junit에서 2 개의 목록 사이에 Assert가 동일

JUnit 테스트 케이스 에서 목록 사이에 동등 어설 션을 어떻게 만들 수 있습니까? 평등은 목록의 내용 사이에 있어야합니다.

예를 들면 다음과 같습니다.

List<String> numbers = Arrays.asList("one", "two", "three");
List<String> numbers2 = Arrays.asList("one", "two", "three");
List<String> numbers3 = Arrays.asList("one", "two", "four");

// numbers should be equal to numbers2
//numbers should not be equal to numbers3



답변

나는 이것이 몇 년 전에 요청되었다는 것을 알고 있습니다. 아마도이 기능은 주변에 없었습니다. 그러나 이제는 이렇게하는 것이 쉽습니다.

@Test
public void test_array_pass()
{
  List<String> actual = Arrays.asList("fee", "fi", "foe");
  List<String> expected = Arrays.asList("fee", "fi", "foe");

  assertThat(actual, is(expected));
  assertThat(actual, is(not(expected)));
}

hamcrest와 함께 최신 버전의 Junit을 설치 한 경우 다음 가져 오기를 추가하십시오.

import static org.junit.Assert.*;
import static org.hamcrest.CoreMatchers.*;

http://junit.org/junit4/javadoc/latest/org/junit/Assert.html#assertThat(T, org.hamcrest.Matcher)

http://junit.org/junit4/javadoc/latest/org/hamcrest/CoreMatchers.html

http://junit.org/junit4/javadoc/latest/org/hamcrest/core/Is.html


답변

문자열로 변환하고 비교하지 마십시오. 이것은 성능에 좋지 않습니다. junit에는 Corematchers 안에 이에 대한 matcher가 있습니다.hasItems

List<Integer> yourList = Arrays.asList(1,2,3,4)
assertThat(yourList, CoreMatchers.hasItems(1,2,3,4,5));

이것이 목록의 요소를 확인하는 더 좋은 방법입니다.


답변

이것은 JUnit 4.3 이하에 적합한 레거시 답변입니다. 최신 버전의 JUnit은 assertThat 메소드에 내장 된 읽기 가능한 실패 메시지를 포함합니다. 가능하면이 질문에 대한 다른 답변을 선호하십시오.

List<E> a = resultFromTest();
List<E> expected = Arrays.asList(new E(), new E(), ...);
assertTrue("Expected 'a' and 'expected' to be equal."+
            "\n  'a'        = "+a+
            "\n  'expected' = "+expected,
            expected.equals(a));

@Paul이이 답변에 대한 그의 언급에서 언급했듯이, 두 개의 Lists는 같습니다.

지정된 객체도리스트 인 경우에만 두리스트의 크기가 동일하고 두리스트의 모든 해당 요소 쌍이 동일합니다. (두 요소 e1e2같으면 동일합니다 (e1==null ? e2==null : e1.equals(e2)).) 즉, 두 요소가 동일한 순서로 동일한 요소를 포함하는 경우 두 목록이 동일하게 정의됩니다. 이 정의는 equals 메소드가 List인터페이스의 다른 구현에서 올바르게 작동하도록합니다 .

인터페이스JavaDoc을List 참조하십시오 .


답변

assertEquals(Object, Object)JUnit4에서 / JUnit을 5 assertThat(actual, is(expected));Hamcrest에서 단지 모두로 작동 다른 답변에서 제안 equals()하고 toString()비교 객체의 클래스 (깊이)에 대한 오버라이드된다.

어설 션의 동등성 테스트 equals()와 테스트 실패 메시지 toString()가 비교 된 개체 에 의존하기 때문에 중요 합니다.
들어 내장과 같은 클래스 String, Integer등등 … 이러한 재정 등의 문제없이 모두 equals()toString(). 그래서 주장 완벽하게 유효 List<String>또는 List<Integer>assertEquals(Object,Object).
그리고이 문제에 대해 : equals()JUnit 테스트에서 어설 션을 쉽게 만들 수있을뿐만 아니라 객체 평등 측면에서 의미가 있기 때문에 클래스에서 재정의해야합니다 .
어설 션을 쉽게 만들려면 다른 방법이 있습니다.
모범 사례로 어설 션 / 매칭 라이브러리를 선호합니다.

다음은 AssertJ 솔루션입니다.

org.assertj.core.api.ListAssert.containsExactly() 그것은 당신이 필요로하는 것입니다 : 그것은 실제 그룹이 javadoc에 명시된 순서대로 주어진 값을 포함하고 다른 것을 포함하지 않는지 확인합니다.

Foo요소를 추가하고 얻을 수 있는 클래스를 가정하십시오 . 그에
대한 단위 테스트 Foo는 두 목록이 동일한 내용을 가지고 있다고 주장합니다.

import org.assertj.core.api.Assertions;
import org.junit.jupiter.api.Test;

@Test
void add() throws Exception {
   Foo foo = new Foo();
   foo.add("One", "Two", "Three");
   Assertions.assertThat(foo.getElements())
             .containsExactly("One", "Two", "Three");
}

AssertJ의 좋은 점은 List예상대로 선언하는 것이 불필요하다는 것입니다. 어설 션이 더 명확 하고 코드를 더 읽기 쉽게 만듭니다.

Assertions.assertThat(foo.getElements())
         .containsExactly("One", "Two", "Three");

그러나 어설 션 / 매치 라이브러리는 반드시 더 필요하기 때문에 필수입니다.
이제 가정 Foo 하지 않습니다 상점 String들하지만,이 Bar인스턴스를이야.
그것은 매우 일반적인 요구입니다. AssertJ를 사용하면 어설 션을 쉽게 작성할 수 있습니다. equals()/hashCode()JUnit 방식에 다음이 필요하지만 요소 클래스가 재정의되지 않더라도 목록 내용이 동일하다고 주장하는 것이 좋습니다 .

import org.assertj.core.api.Assertions;
import static org.assertj.core.groups.Tuple.tuple;
import org.junit.jupiter.api.Test;

@Test
void add() throws Exception {
    Foo foo = new Foo();
    foo.add(new Bar(1, "One"), new Bar(2, "Two"), new Bar(3, "Three"));
    Assertions.assertThat(foo.getElements())
              .extracting(Bar::getId, Bar::getName)
              .containsExactly(tuple(1, "One"),
                               tuple(2, "Two"),
                               tuple(3, "Three"));
}


답변

요소의 순서에 신경 쓰지 않으면 ListAssert.assertEqualsjunit-addons를 권장 합니다.

링크 : http://junit-addons.sourceforge.net/

게으른 Maven 사용자의 경우 :

    <dependency>
        <groupId>junit-addons</groupId>
        <artifactId>junit-addons</artifactId>
        <version>1.4</version>
        <scope>test</scope>
    </dependency>


답변

junit에서 assertEquals 를 사용할 수 있습니다 .

import org.junit.Assert;
import org.junit.Test;

    @Test
    public void test_array_pass()
    {
        List<String> actual = Arrays.asList("fee", "fi", "foe");
        List<String> expected = Arrays.asList("fee", "fi", "foe");
        Assert.assertEquals(actual,expected);
    }

요소의 순서가 다르면 오류를 반환합니다.

모델 객체 목록을 주장하는 경우 특정 모델의 equals 메서드를 재정의해야합니다.

    @Override
    public boolean equals(Object obj) {
        if (obj == this) {
            return true;
        }
        if (obj != null && obj instanceof ModelName) {
            ModelName other = (ModelName) obj;
            return this.getItem().equals(other.getItem()) ;
        }
        return false;
    }

답변

배열 목록을 작성하지 않으려는 경우에도 시도 할 수 있습니다

@Test
public void test_array_pass()
{
  List<String> list = Arrays.asList("fee", "fi", "foe");
  Strint listToString = list.toString();
  Assert.assertTrue(listToString.contains("[fee, fi, foe]"));   // passes  
}