2015-11-06 31 views
0

我有一个类MySchoolAssert.assertEquals

public class MySchool{ 
    private long timestamp; 
    private SchoolEvent event; 
    private Object value; 

    //getter & setters 
    ... 

    @Override 
    public String toString() { 
     return "MySchool [timestamp=" + timestamp + ", event=" 
       + event + ", value=" + value + "]"; 
    } 
} 

SchoolEvent是一个枚举类型:

public static enum SchoolEvent { 
     CEREMONY, HOLIDAY 
    } 

我尝试使用Assert.assertEquals()比较学校两个List:

List<MySchool> schoolList1 = generateSchools(); 
List<MySchool> schoolList2 = readSchoolsFromFile(); 

Assert.assertEquals(schoolList1, schoolList2); 

它失败,出现以下错误:

expected: java.util.ArrayList<[MySchool [timestamp=0, event=CEREMONY, value=null], MySchool [timestamp=0, event=HOLIDAY, value=null]]> 

but was: java.util.ArrayList<[MySchool [timestamp=0, event=CEREMONY, value=null], MySchool [timestamp=0, event=HOLIDAY, value=null]]> 

我不明白为什么错误听起来不像是一个错误,我的意思是只检查错误消息,两个列表中的每个元素对象的每个字段是均等的。

我还检查Java文档有关List#equal,它也说:

two lists are defined to be equal if they contain the same elements in the same order.

那么,为什么在断言()失败?

+1

你的'MySchool'类不会覆盖'equals' ... –

+0

为什么我需要重写'MySchool'中的'equals'?错误消息显示一切都是平等的。 – user842225

+0

因为默认情况下,'equals'只检查对象标识。看到我的答案。 –

回答

2

I don't understand why the error doesn't sound like an error, I mean just check the error message, every field of every element object in two lists are euqal.

是的,但这并不意味着对象被认为是相等的。

您需要覆盖equals()(和hashCode())以便将不同的对象视为相同。默认情况下,equals方法只检查对象身份 ...换句话说,x.equals(y)相当于检查xy默认情况下指的是完全相同的对象。如果您需要不同的行为 - 以便检查某些字段是否相等 - 那么您需要在equals()中指定该行为,并以与此一致的方式实施hashCode()

请注意,这个问题并不依赖于集合。

MySchool school1 = schoolList1.get(0); 
MySchool school2 = schoolList2.get(0); 
Assert.areEqual(school1, school2); // This will fail... 
0

两个对象是相等的,他们equals()方法必须返回true:如果你比较各个对象你会得到同样的问题。

如果两个对象都是SAME对象,则equals()的默认实现仅返回true,但如果它们是具有相同“内容”的不同对象,则返回true。

所以,x.equals(y);可以是true,即使x == y( “是x和y相同的对象”)是false,如果x方法的equals()返回true为参数y。

1

你的类必须实现equals()。我将添加下面的范例:

@Override 
public boolean equals(Object o) { 
    if (this == o) return true; 
    if (o == null || getClass() != o.getClass()) return false; 

    MySchool mySchool = (MySchool) o; 

    if (timestamp != mySchool.timestamp) return false; 
    if (event != mySchool.event) return false; 
    return !(value != null ? !value.equals(mySchool.value) : mySchool.value != null); 

} 

然后我会用hamcrest主张对集合:

public void testTwoEventsAreEquals() throws Exception { 
    List<MySchool> schoolList1 = Arrays.asList(new MySchool(SchoolEvent.CEREMONY), new MySchool(SchoolEvent.HOLIDAY)); 
    List<MySchool> schoolList2 = Arrays.asList(new MySchool(SchoolEvent.CEREMONY), new MySchool(SchoolEvent.HOLIDAY)); 

    assertThat(schoolList1, containsInAnyOrder(schoolList2.toArray())); 
} 

如果你正在使用maven,你必须添加Hamcrest作为一个依赖关系,上面的代码编译。

<dependency> 
    <groupId>org.hamcrest</groupId> 
    <artifactId>hamcrest-all</artifactId> 
    <version>1.3</version> 
</dependency> 
+0

但是你仍然需要重写hashCode()也是对的? – Wizard

+0

@向导不一定。只有当你使用使用散列的集合时,如HashMap。所以如果你把这些MySchool对象放在一个HashMap中,那么答案是肯定的。 – panagdu

0

不要把equals方法由他人建议(对不起,伙计们)。这将是一个生产中的测试代码,它不仅本身是错误的,而且如果您为该类添加另一个字段但忘记更新equals方法?您的测试不会测试您认为他们正在测试的内容。而如果equals方法错了呢?如果它总是返回true,该怎么办?你的测试将永远是绿色的,你会有错误的信心,一切都很好。因为当然谁会为equals方法写一个测试。

我强烈建议使用诸如shazamcrest之类的工具。这允许你只写assertThat(actual, sameBeanAs(expected)),你不必担心任何事情。它不需要对生产代码进行任何更改。无论访问修饰符如何,它都会遍历所有字段。还提供了非常好的诊断功能。它会抛出ComparisonFailure(而不是AssertionError),IDE将为您展示很好的并排比较。

代码:

List<MySchool> schoolList1 = generateSchools(); 
List<MySchool> schoolList2 = readSchoolsFromFile(); 

assertThat(schoolList2, sameBeanAs(schoolList2)); 

相关性需要:

<dependency> 
    <groupId>com.shazam</groupId> 
    <artifactId>shazamcrest</artifactId> 
    <version>0.11</version> 
</dependency> 

诊断你:

Comparison Failure diagnostics

注:

[R请记住使用com.shazam.shazamcrest.MatcherAssert.assertThat,而不要使用hamcrestjunit。它的工作方式与其他assertThat方法完全相同,但是如果与sameBeanAs一起使用,它将丢弃ComparisonFailure,而不是其他AssertionError

+0

谁会为等号方法编写测试?希望每个人都需要一个平等的方法。 –

+0

是的,如果你在生产代码中需要它。但是,如果你需要它进行测试,你会吗?我从来没有见过任何人这样做,我也见过很多这样的例子(即依靠“equals”方法的测试)。并且请注意,其他答案都没有提及它 - 他们都说“没有测试就生成它”。 –

相关问题