2016-04-30 73 views
0

在我工作的項目中,它已決定停止使用fest作爲測試斷言,而是使用assertj。我們正在使用Java 7,我們正在從最新版本2.0M10轉向assertj-core版本2.4.1。代碼庫相當大,但從fest到assertj的過渡一直很順利,基本上改變了導入名稱並應對了重命名的方法。 但是,我注意到在轉換後我們在特定的測試類中得到了測試失敗(我應該添加我們正在使用的JUnit v4.12)。下面我將展示一個小的,獨立的測試用例突出問題:fest和assert-j之間的細微差別與自定義地圖

import java.util.Collection; 
import java.util.HashMap; 
import java.util.Map; 
import java.util.Set; 

import org.junit.Before; 
import org.junit.Test; 

class MyMap implements Map<String, Object> { 
    private Map<String, Object> theMap = new HashMap<>(); 

    @Override 
    public int size() { 
     return theMap.size(); 
    } 

    @Override 
    public boolean isEmpty() { 
     return theMap.isEmpty(); 
    } 

    @Override 
    public boolean containsKey(Object key) { 
     return theMap.containsKey(key); 
    } 

    @Override 
    public boolean containsValue(Object value) { 
     return theMap.containsValue(value); 
    } 

    @Override 
    public Object get(Object key) { 
     return theMap.get(key); 
    } 

    @Override 
    public Object put(String key, Object value) { 
     return theMap.put(key, value); 
    } 

    @Override 
    public Object remove(Object key) { 
     return theMap.remove(key); 
    } 

    @Override 
    public void putAll(Map<? extends String, ? extends Object> m) { 
     theMap.putAll(m); 
    } 

    @Override 
    public void clear() { 
     theMap.clear(); 
    } 

    @Override 
    public Set<String> keySet() { 
     return theMap.keySet(); 
    } 

    @Override 
    public Collection<Object> values() { 
     return theMap.values(); 
    } 

    @Override 
    public Set<java.util.Map.Entry<String, Object>> entrySet() { 
     return theMap.entrySet(); 
    } 
} 

public class TestMapComparison { 
    private Map<String, Object> m1 = new HashMap<>(); 
    private MyMap m2 = new MyMap(); 

    @Before 
    public void before() { 
     m1.put("a", "b"); 
     m2.put("a", "b"); 
    } 

    // Fails with: 
    // java.lang.AssertionError: 
    // expected: <'{'a'='b'} ([email protected])'> 
    // but was: <'{'a'='b'} ([email protected])'> 
    @Test 
    public void test1_Fest_m1_isEqualTo_m2() { 
     org.fest.assertions.api.Assertions.assertThat(m1).isEqualTo(m2); 
    } 

    @Test // Pass 
    public void test2_AssertJ_m1_isEqualTo_m2() { 
     org.assertj.core.api.Assertions.assertThat(m1).isEqualTo(m2); 
    } 

    @Test // Pass 
    public void test3_Fest_m2_isEqualTo_m1() { 
     org.fest.assertions.api.Assertions.assertThat(m2).isEqualTo(m1); 
    } 

    // Fails with: 
    // java.lang.AssertionError: 
    // Expecting: <"{"a"="b"} ([email protected])"> 
    // to be equal to: 
    // <"{"a"="b"} ([email protected])"> but was not. 
    @Test 
    public void test4_AssertJ_m2_isEqualTo_m1() { 
     org.assertj.core.api.Assertions.assertThat(m2).isEqualTo(m1); 
    } 
} 

我這麼長的一段代碼遺憾。從測試結果中可以看出,當使用hashmaps上的isEqualTo()時,fest和assertj之間似乎有區別,其中hashmaps中的一個封裝在實現接口映射的類中。 我的問題是如何處理這個問題?我可以翻轉斷言中的順序,即斷言(b).isEqualTo(a)而不是assertThat(a).isEqualTo(b)。但是我覺得在一個有很多斷言的大型測試課中,要做出這樣一個關於特定斷言的翻版的東西並不奇怪。 fest和assertj之間的差異是預期還是意外?行爲是否可以預期(因爲兩個表達式都失敗了)?我應該如何更新測試用例,是否有更好的方法來處理上面代碼中的場景?感謝您閱讀這些,並感謝您的任何建議!

回答

2

那麼,錯誤是在你的代碼,如果你測試的equals(),至極必須是對稱的合同每個庫會發現錯誤:一等於B當且僅當B等於A.

我只想修復你的代碼,並且很高興能夠通過遷移發現錯誤。我也會改進測試,並做

assertThat(a).isEqualTo(b); 
assertThat(b).isEqualTo(a); 

以確保合同得到滿足。

+0

當然,謝謝你,你是對的。我會加強測試,看看實際的課程,看看問題出在哪裏。再次感謝。 –