You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

AssertJ中usingComparatorForType无法作用于嵌套对象的double属性问题

解决AssertJ嵌套对象中Double精度自定义比较的问题

嘿,我明白你遇到的问题了——想用AssertJ的usingComparatorForType来控制嵌套对象里Double字段的比较精度,但发现嵌套在Foo里的Bar对象的baz字段没生效。这其实是因为你用的isEqualToComparingFieldByFieldRecursively方法有个小坑:它在递归比较时会默认调用对象自身重写的equals方法,而不是你设置的自定义比较器。

要解决这个问题,你需要切换到AssertJ的递归比较API——usingRecursiveComparison(),它专门为这种嵌套字段比较设计,能正确把自定义比较器应用到所有层级的指定类型字段上。

修改后的测试代码

下面是调整后的itComparesFoos测试方法,直接看修改后的写法:

@Test
public void itComparesFoos() {
    Foo a = new Foo(1, 1.4, null);
    Foo b = new Foo(1, 1.45, null);
    Foo c = new Foo(2, 1.4, null);

    assertThat(a).isNotEqualTo(b);
    assertThat(b).isNotEqualTo(c);
    assertThat(a).isNotEqualTo(c);

    // 直接比较Foo的Double字段,原来的写法没问题
    assertThat(a)
        .usingComparatorForType(DOUBLE_COMPARATOR, Double.class)
        .isEqualToComparingFieldByField(b);

    Bar barA = new Bar(1, 1.4);
    Bar barB = new Bar(1, 1.45);

    // 情况1:Foo的其他字段一致,Bar对象完全相同,应该通过
    assertThat(a.withBar(barA))
        .usingRecursiveComparison()
        .isEqualTo(b.withBar(barA));

    // 情况2:Foo的其他字段一致,Bar的baz在精度范围内,用自定义比较器让它通过
    assertThat(a.withBar(barA))
        .usingRecursiveComparison()
        .withComparatorForType(DOUBLE_COMPARATOR, Double.class)
        .isEqualTo(b.withBar(barB));
}

关键细节解释

  • 为什么原来的写法失效?:isEqualToComparingFieldByFieldRecursively在比较Bar对象时,会调用你重写的Bar.equals方法,而这个方法里是用Objects.equals(this.baz, that.baz)直接比较Double值,完全没用到你设置的自定义比较器,所以精度控制自然不生效。
  • usingRecursiveComparison()的优势:它会跳过对象自身的equals实现,直接遍历所有嵌套字段进行比较,并且会把你设置的withComparatorForType应用到所有层级的Double类型字段——不管是Foo自己的baz,还是嵌套Bar里的baz,都会用你的自定义规则比较。
  • 简化写法:如果你的精度需求是“允许一定误差范围”,其实不用自己写Comparator,AssertJ自带了withPrecision方法,更简洁:
    assertThat(a.withBar(barA))
        .usingRecursiveComparison()
        .withPrecision(0.1)
        .isEqualTo(b.withBar(barB));
    
    这个方法专门针对浮点类型,用法更直观。

另外,你的自定义Double比较器也可以用Lambda简化一下:

private static final Comparator<Double> DOUBLE_COMPARATOR = 
    (d1, d2) -> Math.abs(d1 - d2) <= 0.1 ? 0 : 1;

这样调整后,嵌套对象里的Double字段就能正确应用你的精度控制了~

内容的提问来源于stack exchange,提问作者Lorcan O'Neill

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.28 09:31:29