AssertJ中如何使用RecursiveComparisonConfiguration实现递归断言?
使用AssertJ的RecursiveComparisonConfiguration优化实体断言逻辑
问题背景
现有两个实体类HospitalDailyCashProductDetails和HospitalDailyCashCoversDetailsUI,部分属性键名一致但存在格式差异,实体结构如下:
HospitalDailyCashProductDetails(productId=4148, productCode=4148, premiumAmount=600, productDescription=(Hospital Daily Cash Cover), productName=Group Safeguard Insurance, sumInsured=₹ 750.00 per day for up to 30 days, validityPeriod=12 Months, dateOfIssuance=04/03/2024) HospitalDailyCashCoversDetailsUI(premiumAmount=₹600.00, sumInsured=₹ 750.00 per day for up to 30 days, validityPeriod=12 Months, dateOfIssuance=04/03/2024)
原断言逻辑需要逐个属性处理格式差异并单独编写断言,代码如下:
HospitalDailyCashProductDetails hospitalDailyCashProductDetails = testContext.getContext(ScenarioContextKey.HOSPITAL_DAILY_CASH_COVERS); HospitalDailyCashCoversDetailsUI hospitalDailyCashCoversDetailsUI = hospitalDailyCashCovers.getHospitalDailyCashCoversDetailsUI(); String strExpectedPremiumAmount = hospitalDailyCashProductDetails.getPremiumAmount(); String strActualPremiumAmount = hospitalDailyCashCoversDetailsUI.getPremiumAmount(); testContext.softAssertion().assertThat(strActualPremiumAmount).withFailMessage("Expected Premium Amount is %s, but was %s", strExpectedPremiumAmount, strActualPremiumAmount).contains(strExpectedPremiumAmount); String strExpectedSumInsured = hospitalDailyCashProductDetails.getSumInsured().replaceAll("₹","₹"); String strActualSumInsured = hospitalDailyCashCoversDetailsUI.getSumInsured(); testContext.softAssertion().assertThat(strActualSumInsured).withFailMessage("Expected Sum Assured is %s, but was %s", strExpectedSumInsured, strActualSumInsured).isEqualTo(strExpectedSumInsured); String strExpectedValidityPeriod = hospitalDailyCashProductDetails.getValidityPeriod(); String strActualValidityPeriod = hospitalDailyCashCoversDetailsUI.getValidityPeriod(); testContext.softAssertion().assertThat(strActualValidityPeriod).withFailMessage("Expected Validity Period is %s, but was %s", strExpectedValidityPeriod, strActualValidityPeriod).isEqualTo(strExpectedValidityPeriod); String strExpectedDateOfIssuance = hospitalDailyCashProductDetails.getDateOfIssuance(); String strActualDateOfIssuance = hospitalDailyCashCoversDetailsUI.getDateOfIssuance(); testContext.softAssertion().assertThat(strActualDateOfIssuance).withFailMessage("Expected Date Of Insurance is %s, but was %s", strExpectedDateOfIssuance, strActualDateOfIssuance).isEqualTo(strExpectedDateOfIssuance);
现需使用AssertJ的RecursiveComparisonConfiguration优化上述断言逻辑,同时保留自定义的testContext.softAssertion()软断言机制。
优化方案
1. 构建递归比较配置
针对属性的格式差异,为特定字段指定自定义比较规则,同时忽略两个实体中不匹配的字段:
- sumInsured:将预期值中的HTML实体
₹转换为货币符号₹后再与实际值比较 - premiumAmount:提取实际值中的数字部分,判断是否包含预期的纯数字字符串
- 忽略
HospitalDailyCashProductDetails中存在但HospitalDailyCashCoversDetailsUI没有的属性
2. 整合软断言执行递归比较
将配置好的递归比较逻辑整合到自定义软断言中,一次性完成所有匹配属性的断言。
具体代码实现
HospitalDailyCashProductDetails hospitalDailyCashProductDetails = testContext.getContext(ScenarioContextKey.HOSPITAL_DAILY_CASH_COVERS); HospitalDailyCashCoversDetailsUI hospitalDailyCashCoversDetailsUI = hospitalDailyCashCovers.getHospitalDailyCashCoversDetailsUI(); // 构建递归比较配置 RecursiveComparisonConfiguration config = RecursiveComparisonConfiguration.builder() // 处理sumInsured属性的货币符号差异 .withEqualsForFields((expected, actual) -> { String convertedExpected = ((String) expected).replaceAll("₹", "₹"); return convertedExpected.equals(actual); }, "sumInsured") // 处理premiumAmount的格式差异:验证实际值包含预期数字 .withEqualsForFields((expected, actual) -> { String expectedNum = (String) expected; String actualCleaned = ((String) actual).replaceAll("[₹.]", "").trim(); return actualCleaned.contains(expectedNum); }, "premiumAmount") // 忽略两个实体中不匹配的字段 .withIgnoredFields("productId", "productCode", "productDescription", "productName") .build(); // 结合自定义软断言执行递归比较 testContext.softAssertion().assertThat(hospitalDailyCashCoversDetailsUI) .usingRecursiveComparison(config) .withFailMessage("实体属性不匹配,预期: %s,实际: %s", hospitalDailyCashProductDetails, hospitalDailyCashCoversDetailsUI) .isEqualTo(hospitalDailyCashProductDetails);
关键说明
- 递归比较会自动遍历所有匹配的属性,无需逐个编写断言,大幅简化代码
withEqualsForFields针对特定属性的格式差异定制比较逻辑,精准处理字段匹配规则withIgnoredFields避免因实体结构不一致导致的比较错误- 保留自定义软断言机制,所有属性的断言失败都会被收集,不会中断测试执行
内容的提问来源于stack exchange,提问作者DeepakVerma
相关产品推荐
相关产品推荐

