2016-04-30 67 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

当然,谢谢你,你是对的。我会加强测试,看看实际的课程,看看问题出在哪里。再次感谢。 –