簡體   English   中英

使用hamcrest contains()方法比較兩個集合

[英]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的equalshashCode方法。 為了在你自己的對象上使用equals (或者在這種情況下contains ),你需要覆蓋你的類的equalshashCode方法。 這是因為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是一個包含一個元素的列表,這個元素應該是一個列表本身,包含兩個項目iPhoneskateboard

要聲明expectedItemsactualItems具有相同順序的相同元素,請嘗試以下操作:

@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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM