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

AssertJ因toString循环引用报错,如何自定义错误报告不调用toString方法?

解决方案

完全可以实现,AssertJ提供了自定义对象字符串表示的能力,无需修改原有业务代码,以下是两种可行实现方式:

方案1:全局注册自定义表示器(推荐,一次配置全测试生效)

通过自定义Representation重写对象的序列化逻辑,全局生效后所有AssertJ断言都会优先使用你定义的规则生成错误信息:

  1. 自定义表示器实现
import org.assertj.core.presentation.StandardRepresentation;

public class EntityIdRepresentation extends StandardRepresentation {
    @Override
    protected String toStringOf(Object object) {
        // 匹配你所有存在循环引用的实体类,也可判断是否实现了有getId()的通用接口
        if (object instanceof YourEntity) {
            return String.format("YourEntity(id=%s)", ((YourEntity) object).getId());
        }
        // 其他类型走默认逻辑
        return super.toStringOf(object);
    }

    // 如果有多个实体类,可扩展通用判断逻辑,比如通过反射判断是否存在getId()方法:
    // private String tryGetId(Object obj) {
    //     try {
    //         Method getIdMethod = obj.getClass().getMethod("getId");
    //         return String.format("%s(id=%s)", obj.getClass().getSimpleName(), getIdMethod.invoke(obj));
    //     } catch (Exception e) {
    //         return super.toStringOf(obj);
    //     }
    // }
}
  1. 全局注册配置
    在测试类的静态初始化块或者@BeforeAll方法中注册即可:
import org.assertj.core.api.Assertions;
import org.junit.jupiter.api.BeforeAll;

public class YourTest {
    @BeforeAll
    static void configAssertJ() {
        Assertions.setGlobalRepresentation(new EntityIdRepresentation());
    }

    // 你的测试方法,直接写原有断言即可
    @Test
    void testList() {
        assertThat(list1).containsExactly(item1, item2);
    }
}

方案2:针对单次断言单独指定

如果不需要全局生效,只想针对特定断言修改表示逻辑,可以用usingRepresentation方法:

// 直接在断言链上指定自定义表示器即可
assertThat(list1)
    .usingRepresentation(new EntityIdRepresentation())
    .containsExactly(item1, item2);

注意事项

如果你的实体类被AOP、JPA等框架生成了代理子类,判断类型时建议通过父类/接口匹配,或者过滤代理类前缀(如$$EnhancerByCGLIB$$),避免匹配失败。

内容的提问来源于stack exchange,提问作者pirho

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.05 06:12:00