在我正在工作的项目中,已经决定停止将fest用于测试断言,而改为使用assertj。我们正在使用Java 7,并且从fest版本2.0M10迁移到assertj-core版本2.4.1。代码库很大,但是从fest到assertj的过渡很顺利,基本上可以更改导入名称并应对重命名的方法。
但是,我注意到在过渡之后,我们在特定的测试类中遇到了测试失败(我应该补充一点,我们正在使用JUnit v4.12)。下面,我显示了一个小而完整的测试用例,突出了这个问题:

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'} (MyMap@6f5fc7ad)'>
    // but was: <'{'a'='b'} (HashMap@3)'>
    @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"} (MyMap@5aedacd2)">
    // to be equal to:
    // <"{"a"="b"} (HashMap@3)"> but was not.
    @Test
    public void test4_AssertJ_m2_isEqualTo_m1() {
        org.assertj.core.api.Assertions.assertThat(m2).isEqualTo(m1);
    }
}


这么长的代码对不起。从测试结果中可以看出,当在哈希表上使用isEqualTo()时,fest和assertj之间似乎有所不同,其中,哈希表之一封装在实现接口映射的类中。
我的问题是如何处理?我可以翻转断言中的顺序,即具有assertThat(b).isEqualTo(a)而不是具有assertThat(a).isEqualTo(b)。但这对我在具有许多断言的大型测试类中对特定断言进行这样的翻转感到很奇怪。 fest和assertj之间的区别是预期的还是意外的?这是预期的行为吗(因为两个表达式都失败)?我应该如何更新测试用例,是否可以更好地对上述代码中的场景进行相等性检查?感谢您阅读本文并感谢您的任何建议!

最佳答案

好吧,该错误在您的代码中,并且如果您测试equals()的约定,那么每个库都会发现该错误,并且必须对称:A等于B且B等于A。

我将简单地修复您的代码,并很高兴由于迁移而发现了该错误。我也会改善测试并做

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


确保合同履行。

关于java - fest和assert-j与自定义映射之间的细微差别,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/36953638/

10-11 10:41