[英]hamcrest: comparing two collections ob custom class logically using hamcrest
[英]Comparing two collections using hamcrest contains() method
我有兩個集合,我試圖在單元測試中比較相等,但我正在努力使用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
相同的對象,所以我希望斷言為true,但這是我得到的輸出:
[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;
}
}
Collection的.contains(...)
使用Objects的equals
和hashCode
方法。 為了在你自己的對象上使用equals
(或者在這種情況下contains
),你需要覆蓋你的類的equals
和hashCode
方法。 這是因為Java在幕后使用引用,因此即使字段可能相等,Object-references也不是。
在Eclipse中,您可以使用right-mouse click
生成它們 - > Source
- > 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
-class中,則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));
}
assertThat(actualList, is(expectedList));
我不確定這是否是原因,如果這將解決它,因為你使用不同的JUnit庫然后我通常這樣做,我不確定這些語法是否可以使用Asserts。
我真的不認為你真的需要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()));
你基本上斷言expectedItems
是一個包含一個元素的列表,這個元素應該是一個列表本身,包含兩個項目iPhone
和skateboard
。
要聲明expectedItems
和actualItems
具有相同順序的相同元素,請嘗試以下操作:
@Test
public void getAllItems() {
Collection<Item> actualItems = auction.getAllItems(joe);
assertThat(actualItems, contains(iPhone, skateboard));
}
並注意assertThat
期望“實際”對象作為第一個參數而不是“預期”。
或者你也可以這樣做:
@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()])));
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.