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

能否强制AssertJ采用一致内部表示来比较ProtoBuf对象?

Protobuf对象AssertJ递归比较不匹配的解决办法

问题场景

Proto消息定义

message Tags {
  map<string, bool> tagset = 1;
}

message Msg {
  Tags tags = 1;
}

文本格式Proto文件(msg.txtpb)

tags {
  tagset {
    key: "key1"
    value: true
  }
}

单元测试代码

Msg expectedProto = TextFormat.merge(
    new FileReader("msg.txtpb"), Msg.newBuilder()).build();
assertThat(actualProto).usingRecursiveComparison().isEqualTo(expectedProto);

错误提示

field/property 'tags_.tagsSet_.listData' differ:
- actual value  : null
- expected value: [key: "key1" value: true]

field/property 'tags_.tagSet_.mapData' differ:
- actual value  : {"key1"=true}
- expected value: null

field/property 'tags_.tagSet_.mode' differ:
- actual value  : MAP
- expected value: LIST

解决办法

  • 强制TextFormat以MAP模式解析
    问题根源是TextFormat.merge默认用LIST模式存储map数据,和实际Proto对象的MAP模式不匹配。通过指定解析器的MapMode强制统一:

    TextFormat.Parser parser = TextFormat.getParser().withMapMode(TextFormat.MapMode.MAP);
    Msg expectedProto = parser.merge(new FileReader("msg.txtpb"), Msg.newBuilder()).build();
    
  • 让AssertJ忽略内部差异字段
    如果不想修改解析逻辑,可在递归比较时排除这些内部实现字段:

    assertThat(actualProto)
        .usingRecursiveComparison()
        .ignoringFields("tags_.tagSet_.listData", "tags_.tagSet_.mapData", "tags_.tagSet_.mode")
        .isEqualTo(expectedProto);
    
  • 直接使用Protobuf原生equals方法
    Protobuf自动生成的类已经实现了准确的equals逻辑,无需递归比较,直接断言更可靠:

    assertThat(actualProto).isEqualTo(expectedProto);
    

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.14 18:56:06