2014-02-07 114 views
66

我想比较2所列出:Hamcrest比较集合

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) 

我应该怎么写呢?

回答

101

如果要断言两个列表是相同的,没有事情Hamcrest复杂:

assertEquals(expectedList, actual.getList()); 

如果你真的打算执行顺序不敏感的比较,你可以调用containsInAnyOrder可变参数方法并直接提供值:

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

(假设你的列表是String,而不是Agent,在这个例子中)。

如果你真的想调用同样的方法用的List内容:

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

没有这一点,你调用一个参数的方法,创造一个Matcher是希望以匹配Iterable其中每个元素List。这不能用于匹配List

也就是说,您无法将List<Agent>Matcher<Iterable<List<Agent>>相匹配,这是您的代码正在尝试的内容。

+0

对于“如果你真的想用列表的内容调用同样的方法”+1。可悲的是,我无法让自己解决。特别是有一个构造函数需要一个集合。 –

+3

@Tim不完全; 'containsInAnyOrder'要求* all *元素存在,所以第一个断言将失败。如果您想检查*至少*这些元素是否存在,请参阅'hasItems'。 – Joe

+0

是的,你是对的 – Tim

26

我唯一要添加到@乔的回答是,toArray()参数是多余的这里,所以你可以写顺序不敏感的比较如下:

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

不应该这是一条评论吗? – Tim

-3

要顺序保存的使用比较两个列表,

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

这不回答这个问题。 – kamczak

+0

它部分地做。 – rvazquezglez

+0

@rvazquezglez你是什么意思?你为什么这么说?该方法的结果在我的环境中是正确的。 – niaomingjian

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

P.S.任何帮助,以避免被suppresed警告将非常感激。

6

使用现有的Hamcrest库(截至v.2.0.0.0),您必须在Collection上使用Collection.toArray()方法才能使用containsInAnyOrder Matcher。 远更好的将其添加为一个单独的方法来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()); 
} 

其实我最终加入这个方法我的自定义测试库,并用它来增加我的测试用例可读性(因以减少冗长)。

+1

不错,我将使用此帮助程序。这里的断言信息更具信息性:它一个一个地命名缺失的项目,而不仅仅是:列表应该是elem1,elem2,... elem99,但是我得到了elem1,elem2,...,elem98 - 祝你好运找到失踪的人。 – pihentagy

5

为了补充@乔的回答是:

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...)

0

确保您的列表中的Object s已在其上定义equals()。然后

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

的作品。