Java 使用hamcrest contains()方法比较两个集合
我有两个集合,我试图在单元测试中比较它们是否相等,但我正在使用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);
@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文档站点。例如,假设您想检查列表中的每个元素是否都有特定的特征。顺便说一句,如果回答回答了您的问题,那么标记为已回答也会帮助其他人。谢谢!