ArchUnit 可在单元测试中静态检查自定义异常命名是否以 Exception 或 Error 结尾:先筛选继承 Throwable 的顶层非 JDK 类,再校验类名后缀,支持排除例外并提供清晰失败报告。

ArchUnit 可以在单元测试中检查代码的静态结构,包括类名、包名、字段名等命名规范。要验证自定义异常是否遵循命名约定(例如:必须以 Exception 或 Error 结尾),不需要运行时逻辑,只需用 ArchUnit 的 Java 类解析能力 + 自定义规则即可实现。
识别自定义异常类
ArchUnit 通过 `classes().that()` 定义筛选条件。自定义异常通常是继承自 Throwable(或其子类如 Exception、RuntimeException、Error)且不在 JDK 核心包中(如 java.lang、java.util)的非匿名、非合成类。
- 使用
haveSuperClass(Conditionally)或areAssignableTo(Throwable.class)捕获所有异常类型 - 排除 JDK 自带异常:用
and().not(beInAnyPackage("java..", "javax..")) - 确保是顶层类(非内部类/匿名类):加
and().areTopLevelClasses()
定义命名后缀规则
Java 异常命名惯例要求类名以 Exception 或 Error 结尾(如 ValidationException、NetworkError)。ArchUnit 提供 haveSimpleNameEndingWith(...) 直接校验简单类名(不含包路径)。
- 支持多后缀:用
or(haveSimpleNameEndingWith("Exception")).or(haveSimpleNameEndingWith("Error")) - 注意大小写敏感:默认严格匹配,若允许小写可先用
convert(...)统一转为大写再判断 - 避免误判接口或普通类:务必结合“继承自 Throwable”前提,否则可能把
MyExceptionUtil这类名字也纳入检查
编写可执行的 ArchUnit 测试
将上述逻辑组合成一个 ArchRule,并在 JUnit 测试方法中调用 check(classes)。推荐使用 @AnalyzeClasses 注解自动加载项目字节码。
立即学习“Java免费学习笔记(深入)”;
- 添加依赖:
archunit-junit5和archunit(版本建议 1.3.0+) - 测试类加上
@AnalyzeClasses(packages = "com.yourcompany") - 规则示例:
ArchRuleDefinition.classes()<br> .that().areAssignableTo(Throwable.class)<br> .and().areTopLevelClasses()<br> .and().not(beInAnyPackage("java..", "javax.."))<br> .should().haveSimpleNameEndingWith("Exception")<br> .orShould().haveSimpleNameEndingWith("Error")<br> .because("custom exceptions must end with 'Exception' or 'Error'"); - 运行失败时,ArchUnit 会清晰列出违反规则的类名和原因
处理常见例外情况
实际项目中可能存在合理例外,比如工具类 Exceptions(复数形式)、枚举 ErrorCode、或基类 BaseException。可通过 ignoreMethod(...) 或 ignorePackages(...) 排除干扰。
- 忽略特定类:
.and().not(new DescribedPredicate("is BaseException") { ... }) - 忽略某包下所有类:
and().not(beInAnyPackage("com.yourcompany.infra.exception")) - 若需更灵活匹配(如支持
ExceptionBase),可用正则:haveSimpleNameMatching(".*Exception|.*Error")


















