Skip to content

fix: correct data-mask and date-format bugs; add unit tests - #2

Open
Siborne wants to merge 2 commits into
openquartz:mainfrom
Siborne:fix/diff-bugs-and-tests
Open

fix: correct data-mask and date-format bugs; add unit tests#2
Siborne wants to merge 2 commits into
openquartz:mainfrom
Siborne:fix/diff-bugs-and-tests

Conversation

@Siborne

@Siborne Siborne commented Aug 12, 2026

Copy link
Copy Markdown

背景

java-obj-diff 在运行示例与补全测试的过程中,发现并修复了 3 个功能性 bug,同时修正了 1 处接口文档错误;并在此基础上为项目引入了 JUnit 5 单元测试体系(此前项目没有任何自动化测试,只有一个 main 方法形式的演示程序)。

修复内容

1. 邮箱脱敏输出重复的 @EmailDataMaskFormatter

  • 现象desensitizeEmail("wangtest1111@126.com") 输出 ***********w@@126.com,多了一个 @
  • 原因email.substring(atIndex) 本身已包含 @,代码又手动拼接了一个 "@"
  • 修复:去掉手动拼接的 "@",输出 ***********w@126.com
  • 顺带修复:当邮箱以 @ 开头(prefix 为空)时,原逻辑 Stream.limit(-1) 会抛 IllegalArgumentException,现直接原样返回。

2. 时间格式化对 LocalDate / LocalTime 等抛 ClassCastExceptionDateTimeDiffFormatter

  • 现象format(LocalDate, "yyyy-MM-dd")ClassCastException: LocalDate cannot be cast to LocalDateTime
  • 原因TemporalAccessor 分支强制 cast 为 LocalDateTime,而 LocalDateLocalTimeOffsetDateTime 等同样是 TemporalAccessor 却非 LocalDateTime
  • 修复:改为按 TemporalAccessor 直接格式化,并移除未使用的 LocalDateTime import。

3. 手机号脱敏 null 输入 NPE(MobileDataMaskFormatter

  • 现象desensitizePhoneNumber(null)NullPointerExceptionPattern.matcher(null))。
  • 原因:静态方法缺少 null 检查,与 EmailDataMaskFormatterIdCardDataMaskFormatter 的行为不一致。
  • 修复:null 输入直接返回 null,与其余脱敏 formatter 保持一致。

4. 接口文档语义相反(DiffComparable

  • 现象:javadoc 写的是「false: 相同, true: 不同」,与实际语义相反。
  • 事实:所有内置实现(DefaultDiffComparatorBigDecimalEffectiveDiffComparator、示例中的 SelfEnumComparator)及调用方 DiffBuilder 均按「相等 → true」工作。
  • 修复:javadoc 修正为「true: 相同, false: 不同」,避免自定义比较器开发者被误导。

新增单元测试

引入 JUnit Jupiter 5.10.2 与 surefire 3.2.5,新增 6 个测试类、共 46 个用例

测试类 用例数 覆盖内容
DiffUtilsTest 19 同引用/同值无差异、简单字段 diff、@DiffIgnore 忽略、排除字段、@DiffAlias 别名、@DiffFormat 格式化、@DiffCompare 自定义比较器、@DiffBean 嵌套对象、集合比较(自定义类型元素 / JDK 类型元素 / 长度不同按索引对齐)、DiffResult API(isDiff/getNumberOfDiffs/不可变列表/迭代)
DateTimeDiffFormatterTest 7 DateLocalDateTimeLocalDateLocalTime(后两者为本次修复的回归用例)、默认 pattern、null、不支持类型
EmailDataMaskFormatterTest 6 重复 @ 回归、单字符前缀、@ 开头守卫、blank/无 @、非法类型
MobileDataMaskFormatterTest 5 手机号/座机脱敏、非法输入、null(本次修复的回归用例)、非法类型
IdCardDataMaskFormatterTest 4 18 位脱敏、长度校验、null、非法类型
BigDecimalEffectiveDiffComparatorTest 5 忽略尾零相等、不同值、null 处理、非 BigDecimal 类型校验

其中 EmailDataMaskFormatterTestDateTimeDiffFormatterTestMobileDataMaskFormatterTest 分别包含对上述 bug 的回归用例,防止问题复发。

验证结果

mvn clean test
Tests run: 46, Failures: 0, Errors: 0, Skipped: 0
BUILD SUCCESS

其他说明

  • DiffUtils 存在一个既有 API 重载歧义(diffResult(T,T,String...)diffResult(T,T,String,String...) 在传单个 String 时编译不通过),本次未改动 API,测试中以显式数组方式调用规避;是否调整 API 留待后续讨论。

s_hongshibo added 2 commits August 12, 2026 15:08
- EmailDataMaskFormatter: drop duplicated '@' in masked email
  (wangtest1111@126.com -> ***********w@126.com instead of ...w@@126.com)
  and guard against an email starting with '@' (Stream.limit(-1) crash)
- DateTimeDiffFormatter: format any TemporalAccessor instead of casting
  to LocalDateTime (LocalDate/LocalTime previously threw ClassCastException)
- MobileDataMaskFormatter: return null for null input instead of NPE
  (consistent with Email/IdCard mask formatters)
- DiffComparable: fix javadoc, semantics are "true = same" as all
  built-in comparators and callers already behave
- DiffUtilsTest (19): ignore/exclude fields, alias, format, custom
  comparators, nested @DiffBean, collections (custom/JDK element types),
  DiffResult API
- DateTimeDiffFormatterTest (7): Date/LocalDateTime/LocalDate/LocalTime,
  including regressions for the fixed TemporalAccessor cast
- Email/Mobile/IdCardDataMaskFormatterTest (15): masking behavior plus
  regressions for the duplicated '@' and null-NPE fixes
- BigDecimalEffectiveDiffComparatorTest (5): effective value comparison,
  null handling, type validation
- pom.xml: add junit-jupiter 5.10.2 (test scope) + surefire 3.2.5
- .gitignore: ignore .reasonix/ tool directory
@Siborne
Siborne force-pushed the fix/diff-bugs-and-tests branch from 2399861 to 34d07ea Compare August 12, 2026 07:16
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant