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)

我该怎么写?

155144 次浏览

如果你想断言这两个列表是相同的,不要让 Hamcrest 的事情复杂化:

assertEquals(expectedList, actual.getList());

如果您确实打算执行不区分顺序的比较,您可以调用 containsInAnyOrder varargs 方法并直接提供值:

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

(假设您的列表是 String,而不是本例中的 Agent。)

如果您真的希望使用 List的内容调用相同的方法:

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

如果没有这个参数,就只能使用一个参数调用该方法,并创建一个 Matcher,该 Matcher期望匹配 Iterable,其中 每个元素List。这不能用来匹配 List

也就是说,您不能将 List<Agent>Matcher<Iterable<List<Agent>>匹配,这正是您的代码正在尝试的。

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

简短的@Joe 的回答,没有多余的参数。

将两个列表与所保留的顺序(严格顺序)进行比较。

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

如果我们想比较没有一个特定的顺序,我们可以使用以下命令

assertThat(collection, containsInAnyOrder("item1","item2"));

对于对象列表,你可能需要这样的东西:

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")))));
}

如果不想检查对象的顺序,请使用 包含任何订单

另外,如果能帮助我们避免被压制的警告,我们将不胜感激。

对于现有的 Hamcrest 库(从 v.2.0.0.0开始) ,必须对 Collection 使用 Collection.toArray ()方法才能使用 containsInAnyOrder Matcher。 更好的做法是将其作为一个单独的方法添加到 org.hamcrest 中:

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());
}

实际上,我最终将这个方法添加到我的自定义测试库中,并使用它来增加测试用例的可读性(由于较少的冗长性)。

补充@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...)

确保列表中的 Object上定义了 equals(),然后

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

工程。