2011-12-12 81 views
2

爲作業創建測試,我收到一個奇怪的AssertionError異常。爲什麼這個assertion引發AssertionError?

我已經改變了它,直到我到了一個簡單的例子:

List<Integer> elements= new ArrayList<Integer>(); 
elements.add(1); 
elements.add(2); 
elements.add(3); 

Permutation p2 = new Permutation(elements); 
Permutation p1 = new Permutation(elements); 

assertThat(p2, equalTo(p1)); 

Permutation.java:

public class Permutation { 

    private List<Integer> elements; 

    public Permutation(List<Integer> elements) { 
    this.elements = elements; 
    } 

public boolean equals(Permutacion permutation){ 
    if (this.elements.size() != permutation.elements.size()){ 
    return false; 
    } 

    Iterator<Integer> iterThis = this.elements.iterator(); 
    Iterator<Integer> iterOther = permutation.elements.iterator(); 
    while (iterThis.hasNext() && iterOther.hasNext()){ 
    if (iterThis.next() != iterOther.next()){ 
     return false; 
    } 
    } 

    return true; 

} 

兩個JUnit和hamcrest源代碼挖我發現,JUnit的assertThat只有電話在匹配器上匹配。

在這種情況下的匹配方法是:

public boolean matches(Object arg) { 
    return areEqual(arg, object); 
} 

private static boolean areEqual(Object o1, Object o2) { 
    if (o1 == null) { 
     return o2 == null; 
    } else if (o2 != null && isArray(o1)) { 
     return isArray(o2) && areArraysEqual(o1, o2); 
    } else { 
     return o1.equals(o2); 
    } 
} 

其中arg應該是 「P2」 和對象應爲 「P1」。

使用調試器的檢查,(它可以在Hamcrest repository可以瀏覽)

在areEqual方法比較的結果是:

"p2 == null"     false 
"p1 != null"     true  
"p2.getClass().isArray()"  false 
"p2.equals(p1)"     true  
"equalTo(p1).matches(p2)"  false 

因此,大家可以看到,代碼應達到最後其他條件並返回truep2.equals(p1)),但equalTo(p1).matches(p2)回報false

感謝您的幫助

回答

7

爲什麼你會期望p2.equals(p1)返回true?您在Permutation類中未覆蓋equals,因此它將默認使用引用標識。你需要重寫equals(和hashCode,一般來說,匹配等於)來表示排列時的平等含義。

編輯:現在你已經發布了更多的代碼,它更清楚發生了什麼事情。你的equals方法有此簽名:

public boolean equals(Permutacion permutation){ 

覆蓋Object.equals,這是匹配將使用什麼。它會引入一個新的方法,即調試器檢查中調用的方法。如果你寫:

Object o1 = p1; 

然後p2.equals(o1)將顯示在調試false太 - 這就是有效的什麼匹配在做什麼。你的equals方法應該是這個樣子:

@Override 
public boolean equals(Object other) 
{ 
    if (other == null || other.getClass() != this.getClass()) 
    { 
     return false; 
    } 
    Permutation otherPermutation = (Permutation) other; 

    // List.equals should do the right thing here 
    return elements.equals(otherPermutation.elements); 
} 

(你也應該重寫hashCode在對應於這種方式。)

此外:

  • 要麼考慮的情況下elements爲空,或者在構造
  • 平等是最簡單的final類定義
  • 如果你還沒有做防禦驗證它該清單的副本可能會在調用之後被調用者改變;例如,如果您將排列用作地圖中的關鍵點,則可能會導致問題。
+0

對不起,我忘了在問題中添加它,但我已經擁有它。無論如何,我發佈的結果來自eclipse的表達式窗口,不僅僅是一個猜測 –

+0

@JuanGuerrero:不,你*沒有*覆蓋'equals(Object)'。將編輯。 –

+0

謝謝,它的工作。我會將你的答案標記爲已解決 –

相關問題