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

M.K*_*.K. 6 java hamcrest

我有两个集合,我试图在单元测试中比较相等,但我正在努力使用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));

}
Run Code Online (Sandbox Code Playgroud)

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)
Run Code Online (Sandbox Code Playgroud)

请问我在使用该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;
    }

}
Run Code Online (Sandbox Code Playgroud)

Kev*_*sen 4

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

right-mouse click在 Eclipse 中,您可以使用-> 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;
}
Run Code Online (Sandbox Code Playgroud)

如果您将这两个添加到您的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));
}
Run Code Online (Sandbox Code Playgroud)

如果您尝试以下操作:

@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));
}
Run Code Online (Sandbox Code Playgroud)

ExpectedList 现在包含 4 个项目吗?

[Item{name=iPhone}, Item{name=Skateboard}, Item{name=iPhone}, Item{name=Skateboard}]  --> Expected
[Item{name=iPhone}, Item{name=Skateboard}]  --> Actual
Run Code Online (Sandbox Code Playgroud)

在这种情况下,您不应添加这两个项目,因为它们已经存在于列表中。

contains另外,您正在尝试在整个列表中使用。通常contains用于查看列表中是否存在单个项目。所以你可以使用这样的东西:

for(Item i : expectedList){
    assertTrue(actualList.contains(i));
}
Run Code Online (Sandbox Code Playgroud)

或者也许是这样的,如果您使用这些库

assertThat(actualList, is(expectedList));
Run Code Online (Sandbox Code Playgroud)

我不确定这是否是原因,以及这是否会解决它,因为您使用不同的 JUnit 库,然后我通常会这样做,并且我不确定这些带有断言的语法是否可行。