我有两个集合,我试图在单元测试中比较相等,但我正在努力使用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));
}
items
包含与expectedItems
相同的对象,所以我希望断言为真,但这是我得到的输出:
[Item{name=iPhone}, Item{name=Skateboard}] --> Expected
[Item{name=iPhone}, Item{name=Skateboard}] --> Actual
java.lang.AssertionError:
Expected: iterable containing [<[Item{name=iPhone}, Item{name=Skateboard}]>]
but: item 0: was <Item{name=iPhone}>
at org.hamcrest.MatcherAssert.assertThat(MatcherAssert.java:20)
at org.hamcrest.MatcherAssert.assertThat(MatcherAssert.java:8)
请问我在使用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;
}
}
答案 0 :(得分:3)
集合的.contains(...)
使用对象的equals
和hashCode
方法。要在您自己的对象上使用equals
(或在本例中为contains
),您需要覆盖类的equals
和hashCode
方法。这是因为Java在幕后使用引用,所以即使字段可能相等,Object引用也不是。
在Eclipse中,您可以使用right-mouse click
生成它们 - &gt; Source
- &gt; Generate hashCode() and 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;
}
如果您将这两者都添加到Item
课程中,则contains
会有效。
编辑:
我不确定,但是当我查看您的代码时,我认为以下内容可能是错误的:
@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));
}
如果您尝试以下方式:
@Test
public void getAllItems() {
Collection<Item> actualItems = auction.getAllItems(joe);
Collection<Item> expectedItems = Lists.newArrayList();
// First add both items
expectedItems.add(iPhone);
expectedItems.add(skateboard);
// Then print both lists
System.out.println(expectedItems);
System.out.println(items);
assertThat(expectedItems, contains(actualItems));
}
expectedList现在是否包含4个项目?
[Item{name=iPhone}, Item{name=Skateboard}, Item{name=iPhone}, Item{name=Skateboard}] --> Expected
[Item{name=iPhone}, Item{name=Skateboard}] --> Actual
在这种情况下,您不应该添加这两个项目,因为它们已经存在于列表中。
此外,您正尝试在整个列表中使用contains
。通常,contains
用于查看列表中是否存在单个项目。所以你可以使用这样的东西:
for(Item i : expectedList){
assertTrue(actualList.contains(i));
}
or perhaps something like this, in case you use these libraries:
assertThat(actualList, is(expectedList));
我不确定这是否是原因,如果这将解决它,因为你使用不同的JUnit库,我通常会这样做,我不确定这些语法是否可以使用Asserts。
答案 1 :(得分:3)
我真的不认为你真的需要hamcrest。以下列方式之一制作断言不是更容易:
列表在一天结束时仍然是一个对象:
org.junit.Assert.assertEquals(expected, actual)
使用containsAll(..)列表的旧时尚功能:
org.junit.Assert.assertTrue(expectedItems.containsAll(actualItems))
使用断言来实现数组的相等性:
org.junit.Assert.assertArrayEquals(expectedItems.toArray(), actualItems.toArray())
当然你也可以使用hamcrest:
org.hamcrest.MatcherAssert.assertThat(actual, Matchers.containsInAnyOrder(actual.toArray()));
或强>
org.hamcrest.MatcherAssert.assertThat(actual, Matchers.contains(actual.toArray()));
答案 2 :(得分:0)
你基本上断言expectedItems
是一个包含一个元素的列表,这个元素应该是一个包含iPhone
和skateboard
两个项目的列表。
要声明expectedItems
和actualItems
具有相同顺序的相同元素,请尝试以下操作:
@Test
public void getAllItems() {
Collection<Item> actualItems = auction.getAllItems(joe);
assertThat(actualItems, contains(iPhone, skateboard));
}
请注意assertThat
期望&#34;实际&#34;对象作为第一个参数而不是&#34;期望&#34;。
或者你也可以这样做:
@Test
public void getAllItems() {
Collection<Item> actualItems = auction.getAllItems(joe);
Collection<Item> expectedItems = Lists.newArrayList();
expectedItems.add(iPhone);
expectedItems.add(skateboard);
assertThat(actualItems, contains(expectedItems.toArray(new Item[expectedItems.size()])));
}