单元测试等于和哈希码 - 一个复杂的故事

Aug*_*sto 8 java complexity-theory unit-testing equals hashcode

我有道德困境.我的应用程序中有一些值对象,它们是不可变的,非常简单.我用IDE生成了equals和hashcode(在我的例子中是intellij),但这样做,使代码覆盖率下降,加上报告现在表明那些值对象非常复杂(使用圈复杂度量度量)实际上他们很简单.

例如,以下等于在具有3个不可变属性的值对象中.代码复杂度为14(javaNCSS),它有26个执行分支(Cobertura).我还应该补充一点,如果任何方法的复杂度大于10,我就会失败.

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

    TranscriptTaskDetails that = (TranscriptTaskDetails) o;

    if (inputFile != null ? !inputFile.equals(that.inputFile) : that.inputFile != null) {
        return false;
    }
    if (language != that.language) {
        return false;
    }
    if (outputFile != null ? !outputFile.equals(that.outputFile) : that.outputFile != null) {
        return false;
    }

    return true;
}
Run Code Online (Sandbox Code Playgroud)

我想知道其他开发人员使用什么来规避这一点,因为我非常关注复杂性报告,因为根据我的经验,高复杂度指标涉及更多错误,所以这个自动生成的equals和hashcode正在污染报告.

我正在考虑使用来自apache commons-lang的EqualsBuilder和HashcodeBuilder来规避这个问题,但我并不百分之百:S.

编辑

我应该补充一点,我为这个项目编写的代码部分是一个将被其他业务部门使用的库......并且将由不同的团队维护:S.

Don*_*oby 7

我正在考虑使用来自apache commons-lang的EqualsBuilder和HashcodeBuilder来规避这个问题,但我并不百分之百:S.

为什么不使用这些?

使用它们可以减少自己方法的大小和复杂性,并且可以更直观地验证equals和hashCode是否一致地实现.

这当然也是一个好主意,很容易测试equals/hashCode合约是否满足,所以一定要写测试.


Ste*_*n C 5

我认为你真正的问题是过于相信人工测量,例如代码覆盖率的圈复杂度.

明显的事实是:

  • 生成的代码是正确的...模数你选择了正确的平等模型,和
  • 生成的代码并不复杂......或者至少没有比它需要的更复杂.

学会相信自己的判断,并停止依靠工具为您做出设计决策.


我刚才所说的必然结果是,如果您认为可以(并且应该)简化生成的代码,同时仍然确保它对于您当前和预计的用例是正确的,那么请继续并简化它.


顺便说一下,生成的等号/哈希码对可能比手写的更正确...由"普通熊"程序员编写.例如,请注意生成的代码处理空字段和类型比较的谨慎方法.很多开发人员都不会那么做对.