2015-11-06 39 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」方法的測試)。並且請注意,其他答案都沒有提及它 - 他們都說「沒有測試就生成它」。 –

相關問題