如何在JUnit测试中自定义JSON对象的比较逻辑?
我来帮你实现符合需求的JSON转POJO后的比较逻辑,完全匹配你提到的规则:
解决方案:自定义POJO比较逻辑
首先,我们先定义对应的POJO类,假设你的JSON结构对应的POJO是这样的(这里用Lombok简化代码,你也可以手动编写getter/setter,效果一致):
import lombok.Data; import java.time.ZonedDateTime; @Data public class Info { // 这里替换成你实际的4个属性,我用field1/2/3+timestamp做示例 private String field1; private String field2; private String field3; // 对应UTC格式的时间戳字段,比如 "2024-05-20T14:30:45.123Z" 这种格式 private String timestamp; }
接下来,我们编写一个专门的比较工具类,来实现你要求的所有规则:
核心比较逻辑实现
import java.time.format.DateTimeFormatter; import java.time.temporal.ChronoUnit; public class InfoComparator { // 用标准ISO格式解析UTC时间戳,完美兼容常见的UTC字符串格式 private static final DateTimeFormatter UTC_DATE_FORMATTER = DateTimeFormatter.ISO_ZONED_DATE_TIME; /** * 按照指定规则比较实际Info对象和预期Info对象 * @param actual 从实际JSON转换来的Info对象 * @param expected 从预期JSON转换来的Info对象 * @return 所有需要校验的字段都匹配返回true,否则返回false */ public static boolean match(Info actual, Info expected) { // 处理第一个普通字段:如果预期值不为null,就和实际值做equals比较 if (expected.getField1() != null) { if (!expected.getField1().equals(actual.getField1())) { return false; } } // 处理第二个普通字段,逻辑和上面一致 if (expected.getField2() != null) { if (!expected.getField2().equals(actual.getField2())) { return false; } } // 处理第三个普通字段 if (expected.getField3() != null) { if (!expected.getField3().equals(actual.getField3())) { return false; } } // 处理UTC时间戳的特殊比较:忽略秒和毫秒部分 if (expected.getTimestamp() != null) { // 把字符串时间戳解析为带时区的时间对象 var expectedDateTime = ZonedDateTime.parse(expected.getTimestamp(), UTC_DATE_FORMATTER); var actualDateTime = ZonedDateTime.parse(actual.getTimestamp(), UTC_DATE_FORMATTER); // 截断时间到分钟级别(自动丢弃秒、毫秒及更小单位),再比较是否相等 if (!expectedDateTime.truncatedTo(ChronoUnit.MINUTES).equals(actualDateTime.truncatedTo(ChronoUnit.MINUTES))) { return false; } } // 所有需要校验的字段都通过了,返回匹配成功 return true; } }
规则对应说明
- null字段跳过校验:对于预期对象里的每个属性,只要预期值是null,就直接跳过该字段的比较,不管实际对象的对应值是什么。
- 普通字符串严格匹配:非null的普通字符串字段,直接用
String.equals()做严格的内容匹配。 - 时间戳特殊处理:
- 用
ISO_ZONED_DATE_TIME解析标准UTC格式的时间字符串,不需要自己写复杂的格式串。 - 调用
truncatedTo(ChronoUnit.MINUTES)把时间截断到分钟,这样秒、毫秒的差异就会被忽略,只比较到年-月-日-时-分的部分。
- 用
使用示例
你可以像这样调用比较方法:
public class Demo { public static void main(String[] args) { Info actualInfo = new Info(); actualInfo.setField1("hello"); actualInfo.setTimestamp("2024-06-10T09:25:33.456Z"); Info expectedInfo = new Info(); expectedInfo.setField1("hello"); expectedInfo.setTimestamp("2024-06-10T09:25:00.000Z"); // 这里会返回true,因为时间戳截断到分钟后完全一致 boolean isMatched = InfoComparator.match(actualInfo, expectedInfo); System.out.println(isMatched); // 输出 true } }
如果你的POJO属性名称、数量和示例不同,只需要修改比较方法里对应的字段判断逻辑就行。要是你的时间戳不是标准ISO格式,也可以自定义DateTimeFormatter的格式字符串来适配,比如DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'")。
内容的提问来源于stack exchange,提问作者rbqa
相关产品推荐
相关产品推荐

