Java 汉克雷斯特比较系列

Java 汉克雷斯特比较系列,java,junit,hamcrest,Java,Junit,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>>) meth

我试图比较两个列表:

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)

java:assertThat找不到合适的方法(java.util.List,org.hamcrest.Matcher如果您想断言两个列表是相同的,请不要用hamcrest使事情复杂化:

assertEquals(expectedList, actual.getList());
如果确实要执行不区分顺序的比较,可以调用
containsInAnyOrder
varargs方法并直接提供值:

assertThat(actual.getList(), containsInAnyOrder("item1", "item2"));
(例如,假设您的列表是
String
,而不是
Agent
。)

如果确实要使用
列表的内容调用相同的方法

assertThat(actual.getList(), containsInAnyOrder(expectedList.toArray(new String[expectedList.size()]));
如果不这样做,您将使用单个参数调用该方法,并创建一个
匹配器
,该匹配器期望匹配一个
Iterable
,其中每个元素都是一个
列表
。这不能用于匹配
列表

也就是说,不能将
List
Matcher
List-actual=Arrays.asList(1L,2L)进行匹配;
预期列表=数组.asList(2L,1L);
资产(实际,包含任何订单(预期为.toArray());

没有冗余参数的@Joe答案的较短版本。

要比较两个保留顺序的列表

assertThat(actualList, contains("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")))));
}
import static org.hamcrest.matcherasert.assertThat;
导入静态org.hamcrest.Matchers.contains;
导入静态org.hamcrest.Matchers.allOf;
导入静态org.hamcrest.beans.HasPropertyWithValue.hasProperty;
导入静态org.hamcrest.Matchers.is;
@试验
@抑制警告(“未选中”)
公共无效测试返回列表(){
排列();
List myList=act();
资产(myList,包含(allOf(hasProperty(“id”),为(7L)),
hasProperty(“名称”,即“testName1”),
hasProperty(“描述”,即(“testDesc1”)),
allOf(hasProperty(“id”),是(11L)),
hasProperty(“名称”,即(“testName2”)),
hasProperty(“描述”,即(“testDesc2”));
}
如果不希望检查对象的顺序,请使用


另外,我们非常感谢您为避免警告而提供的任何帮助。

对于现有的Hamcrest库(从v.2.0.0.0开始),您必须对您的集合使用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());
}

public static org.hamcrest.Matcher补充@Joe的答案:

Hamcrest为您提供了三种主要方法来匹配列表:

包含
检查是否匹配按顺序计数的所有元素,如果列表中有更多或更少的元素,则列表将失败

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

确保列表中的
对象定义了
equals()
,然后

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

有效。

+1表示“如果您真的想用列表的内容调用相同的方法”。遗憾的是,我自己无法解决这个问题。特别是有一个构造函数接受集合。@Tim不太清楚;
containsInAnyOrder
要求所有元素都存在,因此第一个断言将失败。如果要检查至少这些元素是否存在,请参阅
hasItems
。如果使用containsInAnyOrder,您应该首先确保两个列表的大小相同…如果
actual.getList()
恰好包含
“item1”、“item3”、“item2”
,则测试将通过,并且您可能希望确保它只包含列出的项…在这种情况下,您可以使用
assertThat(actual.getList().size(),equalTo(2))
在containsInAnyOrder之前,这样可以确保两个列表的内容相同。@Martin您考虑的是
hasItems
。这里不需要额外检查。请参阅上面对Tim的注释,还有Kotlin用户:不要忘了添加扩展运算符(
*expectedList.toTypedArray()
)当将数组作为varargs传递时!这并不能回答问题。它部分地回答了问题。@rvazquezglez你是什么意思?为什么这么说?该方法的结果在我的环境中是正确的。@niaomingjian代码正在检查
actualist
是否包含
contains
matcher中的元素,如果elements的顺序不同,如果它包含多个元素或缺少一个元素,它也会失败。@rvazquezglez因此代码的目的是检查精确的相等性(相同的长度、值和顺序)在两个列表中,对吗?很好的一个,我将使用这个帮助程序。这里的断言消息更具信息性:它一个接一个地命名缺少的项,而不仅仅是:列表应该是elem1,elem2,…elem99,但我得到了elem1,elem2,…elem98——祝你好运找到缺少的一个。如果列表项不是原始类型,那么这个决定很好。有类型安全的方法吗为什么要这样做?
assertThat(generatedList, is(equalTo(expectedList)));