Hamcrest 비교 컬렉션


114

두 목록을 비교하려고합니다.

assertThat(actual.getList(), is(Matchers.containsInAnyOrder(expectedList)));

하지만 생각

java: no suitable method found for assertThat(java.util.List<Agent>,org.hamcrest.Matcher<java.lang.Iterable<? extends model.Agents>>)
method org.junit.Assert.<T>assertThat(T,org.hamcrest.Matcher<T>) is not applicable
  (no instance(s) of type variable(s) T exist so that argument type org.hamcrest.Matcher<java.lang.Iterable<? extends model.Agents>> conforms to formal parameter type org.hamcrest.Matcher<T>)
method org.junit.Assert.<T>assertThat(java.lang.String,T,org.hamcrest.Matcher<T>) is not applicable
  (cannot instantiate from arguments because actual and formal argument lists differ in length)

어떻게 작성해야합니까?

답변:


161

두 목록이 동일하다고 주장하려면 Hamcrest를 사용하여 복잡하게 만들지 마십시오.

assertEquals(expectedList, actual.getList());

순서를 구분하지 않는 비교를 수행하려는 경우 containsInAnyOrdervarargs 메서드를 호출하고 값을 직접 제공 할 수 있습니다.

assertThat(actual.getList(), containsInAnyOrder("item1", "item2"));

( 이 예에서는 목록 이이 String아니라 라고 가정합니다 Agent.)

a의 내용으로 동일한 메서드를 정말로 호출하려면 List:

assertThat(actual.getList(), containsInAnyOrder(expectedList.toArray(new String[expectedList.size()]));

이 없다면, 당신은 하나의 인수를 사용하여 메소드를 호출하고을 만들 Matcher예상하는가 일치하는 것을 Iterable어디에 각 요소가 입니다 List. .NET과 일치하는 데 사용할 수 없습니다 List.

즉, 당신은 일치하지 수 List<Agent>로모그래퍼 Matcher<Iterable<List<Agent>>코드를 시도하고 무엇이다.


"목록의 내용으로 동일한 메소드를 호출하려는 경우"에 대한 +1. 슬프게도 나는 그것을 스스로 해결할 수 없었다. 특히 컬렉션을받는 생성자가 있습니다.
Eyad Ebrahim 2014.10.06

3
@ 팀 정답이 아닙니다. 첫 번째 주장이 실패하도록 모든 요소가 containsInAnyOrder있어야합니다 . 보기 당신이 있는지 확인하려면 적어도 이러한 요소가 존재한다. hasItems
Joe

4
containsInAnyOrder를 사용하는 경우 먼저 두 목록의 크기가 동일한 지 확인해야합니다 ... actual.getList()를 포함 "item1", "item3", "item2"하는 경우 테스트가 통과되고 나열된 항목 만 포함되도록 할 수 있습니다 ...이 경우 사용할 수 있습니다. assertThat(actual.getList().size(), equalTo(2));containsInAnyOrder 이전에 이렇게하면 두 목록이 동일한 내용을 갖도록합니다.
Martin

1
@Martin 당신이 생각하고 hasItems있습니다. 여기에서는 추가 검사가 필요하지 않습니다. 위의 Tim에 대한 주석과 Hamcrest의 hasItems, contains 및 containsInAnyOrder는 어떻게 다릅니 까?

1
Kotlin 사용자 : *expectedList.toTypedArray()배열을 varargs로 전달할 때 스프레드 연산자 ( ) 를 추가하는 것을 잊지 마십시오 !
James Bowman

62
List<Long> actual = Arrays.asList(1L, 2L);
List<Long> expected = Arrays.asList(2L, 1L);
assertThat(actual, containsInAnyOrder(expected.toArray()));

중복 매개 변수가없는 @Joe의 답변의 짧은 버전.


28

@Joe의 대답을 보완하려면 다음을 수행하십시오.

Hamcrest는 목록을 일치시키는 세 가지 주요 방법을 제공합니다.

contains 순서를 세는 모든 요소가 일치하는지 확인합니다. 목록에 요소가 더 많거나 적 으면 실패합니다.

containsInAnyOrder 모든 요소와 일치하는지 확인하고 순서는 중요하지 않습니다. 목록에 요소가 더 많거나 적 으면 실패합니다.

hasItems 지정된 개체 만 확인합니다. 목록에 더 많은 항목이 있는지 여부는 중요하지 않습니다.

hasItem 하나의 개체 만 확인합니다. 목록에 더 많은 항목이 있는지 여부는 중요하지 않습니다.

그들 모두는 객체 목록을 수신하고 equals비교를위한 방법을 사용 하거나 언급 된 @borjab와 같은 다른 매처와 혼합 될 수 있습니다.

assertThat(myList , contains(allOf(hasProperty("id", is(7L)), 
                                   hasProperty("name", is("testName1")),
                                   hasProperty("description", is("testDesc1"))),
                             allOf(hasProperty("id", is(11L)), 
                                   hasProperty("name", is("testName2")),
                                   hasProperty("description", is("testDesc2")))));

http://hamcrest.org/JavaHamcrest/javadoc/1.3/org/hamcrest/Matchers.html#contains (E ...) http://hamcrest.org/JavaHamcrest/javadoc/1.3/org/hamcrest/Matchers.html #containsInAnyOrder (java.util.Collection) http://hamcrest.org/JavaHamcrest/javadoc/1.3/org/hamcrest/Matchers.html#hasItems (T ...)


파티에 조금 늦었지만 각 방법의 차이점에 대한 설명에 감사드립니다.
Marcos de Andrade

목록 항목이 기본 유형이 아닌 경우 훌륭한 결정입니다.
Stanislav Tsepa

이 작업을 수행하는 안전한 방법이 있습니까?
andresp

15

기존 Hamcrest 라이브러리 (v.2.0.0.0 기준)에서는 containsInAnyOrder Matcher를 사용하기 위해 Collection에서 Collection.toArray () 메서드를 사용해야합니다. org.hamcrest.Matchers에 별도의 메소드로 추가하는 것이 훨씬 좋습니다.

public static <T> org.hamcrest.Matcher<java.lang.Iterable<? extends T>> containsInAnyOrder(Collection<T> items) {
    return org.hamcrest.collection.IsIterableContainingInAnyOrder.<T>containsInAnyOrder((T[]) items.toArray());
}

실제로이 메서드를 사용자 지정 테스트 라이브러리에 추가하고 테스트 사례의 가독성을 높이는 데 사용했습니다 (더 적은 자세한 정보로 인해).


2
이 도우미를 사용하겠습니다. 여기에있는 assert 메시지는 더 많은 정보를 제공합니다. 누락 된 항목의 이름을 하나씩 지정하는 것이 아니라, 목록은 elem1, elem2, .. elem99이어야하지만 elem1, elem2, ..., elem98이 있습니다. 행운을 빕니다 잃어버린 것을 찾는 것.
pihentagy

3

Object목록 의 s가 equals()정의되어 있는지 확인하십시오 . 그때

    assertThat(generatedList,is(equalTo(expectedList)));

공장.


1

객체 목록의 경우 다음과 같은 것이 필요할 수 있습니다.

import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.contains;
import static org.hamcrest.Matchers.allOf;
import static org.hamcrest.beans.HasPropertyWithValue.hasProperty;
import static org.hamcrest.Matchers.is;

@Test
@SuppressWarnings("unchecked")
public void test_returnsList(){

    arrange();
  
    List<MyBean> myList = act();
    
    assertThat(myList , contains(allOf(hasProperty("id",          is(7L)), 
                                       hasProperty("name",        is("testName1")),
                                       hasProperty("description", is("testDesc1"))),
                                 allOf(hasProperty("id",          is(11L)), 
                                       hasProperty("name",        is("testName2")),
                                       hasProperty("description", is("testDesc2")))));
}

객체의 순서를 확인하지 않으려면 containsInAnyOrder를 사용하십시오 .

추신 : 예상되는 경고를 피하는 데 도움을 주시면 정말 감사하겠습니다.


-3

두 목록을 순서 보존 사용과 비교하려면

assertThat(actualList, contains("item1","item2"));

이것은 질문에 대한 답이 아닙니다.
kamczak

부분적으로 그렇습니다.
rvazquezglez

@rvazquezglez 무슨 말이야? 왜 그런 말을 해? 방법의 결과는 내 환경에 맞습니다.
niaomingjian

@niaomingjian 코드는 actualListcontainsmatcher 내부에 요소 가 포함되어 있는지 확인합니다. 요소가 동일한 순서가 아니면 실패하고 더 많은 요소를 포함하거나 누락 된 경우에도 실패합니다.
rvazquezglez

@rvazquezglez 그래서 코드의 목적은 두 목록에서 정확한 동등성 (동일한 길이, 값 및 순서)을 검사하는 것입니다.
niaomingjian
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.