欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

单元测试中对对象进行Assert比较

程序员文章站 2023-10-21 19:27:23
在单测中,当期望结果(Expect)和实际结果(Actual)都是对象时,进行Assert.assertEquals判断时,可能会不符合预期,我们认为符合预期的测试结果还是失败,主要还是对象equals方法导致的。原因分析解决方法具体实现......

在单元测试中,当期望结果(Expect)和实际结果(Actual)都是对象时,进行Assert.assertEquals判断时,可能会不符合预期,我们认为符合预期的测试结果还是失败,
主要还是对象equals比较不等导致的。

原因分析

如果选用junit框架,当调用Assert.assertEquals(expected, actual),最终会
调用对象当equals方法:

private static boolean isEquals(Object expected, Object actual) {
        return expected.equals(actual);
    }

我们知道,Object是所有类的父类,其equals方法实现

public boolean equals(Object obj) {
        return (this == obj);
    }

这就引出另一个问题,equals如何比较,equals和=有何不同?
this 和 obj都是对象的引用,也就是对于任何非空的参考值x和y ,当且仅当x和y引用相同的对象( x == y具有值true )时,该方法返回true 。

解决方法

重写对象的equals方法。参见jdk官方文档,为了避免重写equals方法引入该对象的其它操作漏洞,一定要实现等价关系。
public boolean equals(Object obj)

 equals方法在非空对象引用上实现等价关系:
 自反性 :对于任何非空的参考值x ,x.equals(x)应该返回true 。
 对称性 :对于任何非空引用值x和y , x.equals(y)应该返回true当且仅当y.equals(x)回报true 。
 传递性 :对于任何非空引用值x , y和z ,如果x.equals(y)回报true个y.equals(z)回报true ,然后x.equals(z)应该返回true 。
 一致性 :对于任何非空引用值x和y ,多次调用x.equals(y)始终返回true或始终返回false ,没有设置中使用的信息equals比较上的对象被修改。
 对于任何非空的参考值x , x.equals(null)应该返回false 。

请注意,无论何时覆盖该方法,通常需要覆盖hashCode方法,以便维护hashCode方法的通用合同,该方法规定相等的对象必须具有相等的哈希码。

  hashCode的总合同是:
  只要在执行Java应用程序时多次在同一个对象上调用该方法, hashCode方法必须始终返回相同的整数,前提是修改了对象中equals比较中的信息。 该整数不需要从一个应用程序的执行到相同应用程序的另一个执行保持一致。
  如果根据equals(Object)方法两个对象相等,则在两个对象中的每个对象上调用hashCode方法必须产生相同的整数结果。
  不要求如果两个对象根据equals(java.lang.Object)方法不相等,那么在两个对象中的每个对象上调用hashCode方法必须产生不同的整数结果。 但是,程序员应该意识到,为不等对象生成不同的整数结果可能会提高哈希表的性能。
 尽可能多的合理实用,由类别Object定义的hashCode方法确实为不同对象返回不同的整数。 (这通常通过将对象的内部地址转换为整数来实现,但Java的编程语言不需要此实现技术。)

哈希冲突是所有哈希函数无法完全避免的,只能尽量的减少冲突。所以也无法保证对于不同的对象,其hashCode完全不同。

具体实现

    @Builder @Setter @Getter
    public static class Tag extends Object {
        private Integer id;
        private String name;
        private float confidence;

        @Override
        public int hashCode() {
            return Objects.hash(this.id, this.name, this.confidence);
        }

        @Override
        public boolean equals(Object obj) {
            if (obj == this) {
                return true;
            }

            if (obj == null) {
                return false;
            }
            Tag tag = (Tag) obj;
            if (tag.getId() == this.id
            && tag.getName().equals(this.name)
            && tag.getConfidence() == this.confidence) {
                return true;
            }
            return false;
        }

本文地址:https://blog.csdn.net/tyut_aa/article/details/107044269