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

如何用AssertJ递归比较字段名不同但值相同的两个对象

错误原因说明

你之前使用的withEqualsForFields仅适用于同名字段的自定义相等判断,无法解决字段名不匹配的问题。AssertJ在执行递归比较前会先校验目标对象是否包含源对象的所有字段,由于Entity不存在dtoFieldA、dtoFieldB、dtoFieldC三个字段,会直接抛出你遇到的错误,不会执行自定义的BiPredicate逻辑。


正确方案(要求AssertJ版本 >= 3.18.0)

AssertJ从3.18.0版本开始提供withFieldMappingAPI,专门用于处理字段名不匹配的映射场景,配置示例如下:

import static org.assertj.core.api.Assertions.assertThat;

// 测试代码
assertThat(dto)
    .usingRecursiveComparison()
    // 按 源字段(DTO字段名) -> 目标字段(Entity字段名) 规则配置映射
    .withFieldMapping("dtoFieldA", "entityFieldA")
    .withFieldMapping("dtoFieldB", "entityFieldB")
    .withFieldMapping("dtoFieldC", "entityFieldC")
    .isEqualTo(entity);

以上配置会自动完成:

  • sameNameField1、sameNameField2两个同名字段的自动值比较
  • 三个不同名字段按照映射关系匹配后比较值
  • 不需要额外自定义BiPredicate即可完成普通值相等判断

如果有特殊比较逻辑(比如忽略大小写、空值特殊处理等),可以在配置映射后叠加自定义比较规则:

// 示例:dtoFieldA和entityFieldA比较时忽略大小写
BiPredicate<String, String> fieldAComparator = (dtoVal, entityVal) -> dtoVal.equalsIgnoreCase(entityVal);

assertThat(dto)
    .usingRecursiveComparison()
    .withFieldMapping("dtoFieldA", "entityFieldA")
    .withFieldMapping("dtoFieldB", "entityFieldB")
    .withFieldMapping("dtoFieldC", "entityFieldC")
    .withEqualsForFields(fieldAComparator, "dtoFieldA")
    .isEqualTo(entity);

低版本兼容方案(AssertJ < 3.18.0)

如果使用的AssertJ版本不支持字段映射功能,可以先忽略不匹配的字段,再单独校验这几个字段:

// 先递归比较所有同名字段,忽略三个不匹配的DTO字段
assertThat(dto)
    .usingRecursiveComparison()
    .ignoringFields("dtoFieldA", "dtoFieldB", "dtoFieldC")
    .isEqualTo(entity);

// 单独校验三个不同名字段的值
assertThat(dto.getDtoFieldA()).isEqualTo(entity.getEntityFieldA());
assertThat(dto.getDtoFieldB()).isEqualTo(entity.getEntityFieldB());
assertThat(dto.getDtoFieldC()).isEqualTo(entity.getEntityFieldC());

内容的提问来源于stack exchange,提问作者Bartłomiej Adamczyk

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.03 15:27:01