Java 使用hamcrest contains()方法比较两个集合

Java 使用hamcrest contains()方法比较两个集合,java,hamcrest,Java,Hamcrest,我有两个集合,我试图在单元测试中比较它们是否相等,但我正在使用contains方法。以下是我所拥有的: @Test public void getAllItems() { Collection<Item> actualItems = auction.getAllItems(joe); Collection<Item> expectedItems = Lists.newArrayList(); expectedItems.add(iPhone);

我有两个集合,我试图在单元测试中比较它们是否相等,但我正在使用contains方法。以下是我所拥有的:

@Test
public void getAllItems() {

    Collection<Item> actualItems = auction.getAllItems(joe);
    Collection<Item> expectedItems = Lists.newArrayList();
    expectedItems.add(iPhone);
    expectedItems.add(skateboard);
    assertThat(expectedItems, contains(actualItems));

}
org.junit.Assert.assertEquals(expected, actual)
请您帮助我使用
contains
方法时哪里出了问题

public class Item {

    private String name;

    public Item(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String toString() {
        return Objects.toStringHelper(this).add("name", name).toString();
    }

    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + ((name == null) ? 0 : name.hashCode());
        return result;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        Item other = (Item) obj;
        if (name == null) {
            if (other.name != null)
                return false;
        } else if (!name.equals(other.name))
            return false;
        return true;
    }

}
org.junit.Assert.assertEquals(expected, actual)

集合的
.contains(…)
使用对象的
equals
hashCode
方法。为了在您自己的对象上使用
equals
(或者在本例中
包含
),您需要重写类的
equals
hashCode
方法。这是因为Java在幕后使用引用,所以即使字段可能相等,对象引用也不相等

org.junit.Assert.assertEquals(expected, actual)
在Eclipse中,您可以使用
鼠标右键单击
->
源代码
->
生成hashCode()和equals()…
。但是,由于您从未声明要使用Eclipse,下面是生成的方法示例:

// Overriding this class' equals and hashCode methods for Object comparing purposes 
// using the Collection's contains
// contains does the following behind the scenes: Check if both inputs aren't null, 
// check if the HashCodes match, check if the Objects are equal.
// Therefore to use the Collection's contains for Objects with the same fields, we
// need to override the Object's equals and hashCode methods
// These methods below are generated by Eclipse itself using "Source -> Generate 
// hashCode() and equals()..."
@Override
public int hashCode() {
    final int prime = 31;
    int result = 1;
    result = prime * result + ((name == null) ? 0 : name.hashCode());
    return result;
}
@Override
public boolean equals(Object obj) {
    if(this == obj)
        return true;
    if(obj == null)
        return false;
    if(getClass() != obj.getClass())
        return false;
    Item other = (Item) obj;
    if(name == null){
        if(other.name != null)
            return false;
    }
    else if(!name.equals(other.name))
        return false;
    return true;
}
org.junit.Assert.assertEquals(expected, actual)
如果将这两个项都添加到
-类中,则
包含的
将起作用

org.junit.Assert.assertEquals(expected, actual)

编辑:

org.junit.Assert.assertEquals(expected, actual)
我不确定,但当我查看您的代码时,我认为以下可能是错误的:

@Test
public void getAllItems() {

    Collection<Item> actualItems = auction.getAllItems(joe);
    Collection<Item> expectedItems = Lists.newArrayList();

    // You first print both lists
    System.out.println(expectedItems);
    System.out.println(items);

    // And then add the two items to the expectedItems
    expectedItems.add(iPhone);
    expectedItems.add(skateboard);
    assertThat(expectedItems, contains(actualItems));
}
org.junit.Assert.assertEquals(expected, actual)
在这种情况下,您不应该添加这两项,因为它们已经存在于列表中

org.junit.Assert.assertEquals(expected, actual)
此外,您还试图在整个列表中使用
包含的
。通常,
包含
用于查看列表中是否存在单个项目。所以你可以用这样的方法:

for(Item i : expectedList){
    assertTrue(actualList.contains(i));
}
org.junit.Assert.assertEquals(expected, actual)
:

org.junit.Assert.assertEquals(expected, actual)

我不确定这是否是原因,也不确定这是否能解决问题,因为您使用的是不同的JUnit库,我通常会这样做,而且我不确定这些断言语法是否可行。

我真的认为您实际上不需要hamcrest。通过以下方式之一进行资产确认不是更容易吗:

org.junit.Assert.assertEquals(expected, actual)
一天结束时,列表仍然是一个对象:

org.junit.Assert.assertEquals(expected, actual)
列表的旧式功能,使用:

org.junit.Assert.assertEquals(expected, actual)
对数组的相等性使用断言:

org.junit.Assert.assertEquals(expected, actual)
org.junit.Assert.assertArrayEquals(expectedItems.toArray(), actualItems.toArray())
当然,您也可以使用:

org.junit.Assert.assertEquals(expected, actual)

org.junit.Assert.assertEquals(expected, actual)
org.hamcrest.MatcherAssert.assertThat(actual, Matchers.contains(actual.toArray()));

您基本上断言
expectedItems
是一个包含一个元素的列表,而这个元素本身应该是一个包含两个项目
iPhone
skateboard
的列表

org.junit.Assert.assertEquals(expected, actual)
要断言
expectedItems
implementItems
具有相同顺序的相同元素,请尝试以下操作:

org.junit.Assert.assertEquals(expected, actual)
@Test
public void getAllItems() {

    Collection<Item> actualItems = auction.getAllItems(joe);

    assertThat(actualItems, contains(iPhone, skateboard));
}

可能有助于查看您的
Item
实现。您可能希望在Item中定义一个equals方法。所以您希望您的项列表包含一个项列表?或者您希望您的项目列表包含项目吗?就我所见,
contains
是一个varargs方法,它不是基于
集合的→ <代码>资产(expectedItems,包含(items.toArray())…你想得太多了。应该是
assertThat(实现项,is(等于(预期项))
.From and answer by@jimjaret to一个类似的问题:我添加了上述方法,但仍然不起作用。给了我同样的消息。我已经用类项的新定义更新了帖子。@I.K.我已经对我的答案进行了编辑,尽管我不完全确定这是否能解决您的问题。实施项包含一个iphone和一个kateboard。对于expectedItems,我手动插入iPhone和滑板,因为这是我所期望的。然后我做了assertThat。我添加了system out语句以澄清帖子,但我可能失败了。因此每个集合中应该有两个项。感谢您的尝试。@I.K.啊,好的。无论如何,如果我不知道,包含的内容对整个列表都不起作用ot搞错了,所以您应该检查列表中是否每个项目都有for循环,或者应该使用类似于
assertThat(actualList,is(expectedList))的东西;
将整个列表相互比较。我最后使用了
containsAll
。但我想知道如何使用Hamcrest库。它声称它可以比较两个集合,但我正在努力让它工作。@I.K.我明白你的意思…所以我添加了一些额外的建议,包括Hamcrest matchers。它们回答了你的问题吗所以我想自然的问题是,当junit库能够处理比较集合时,hamcrest有什么好处。一般来说,hamcrest提供了junit没有的额外功能吗?正如我在最初的回答中提到的,使用hamcrest的这种断言没有明显的好处。但是它的匹配器非常强大,就像你在eir文档站点。例如,假设您想检查列表中的每个元素是否都有特定的特征。顺便说一句,如果回答回答了您的问题,那么标记为已回答也会帮助其他人。谢谢!