archunit测试不执行因注解缺失或junit版本冲突,需用@analyzeclasses或@runwith+@test;包依赖规则主语须明确,如controller不能调service应以controller包为起点;扫描范围须显式限定,避免超时;需过滤lombok/spring代理等干扰源。

ArchUnit测试类为什么总不执行?
ArchUnit测试默认是普通JUnit测试,但容易被IDE或构建工具忽略——尤其当测试类没加@Test注解、或用的是JUnit 5却引入了JUnit 4的archunit-junit4依赖时。
- 确保测试类使用
@AnalyzeClasses(ArchUnit 1.0+)或@RunWith(ArchUnitRunner.class)(旧版),且方法上有@Test - Maven里必须排除掉冲突的JUnit版本,比如Spring Boot 3项目要显式声明
junit-jupiter,不能靠传递依赖 - IntelliJ中右键运行单测前,先确认测试框架识别为“JUnit 5”;若显示“JUnit 4”,说明
archunit-junit4还在classpath里
怎么写一条真正生效的包依赖规则?
新手常写noClasses().should().accessClassesThat().resideInAnyPackage("..service.."),结果跑过却没拦住违规调用——因为ArchUnit默认只扫描@AnalyzeClasses指定的包,且accessClassesThat匹配的是“被访问的类”,不是“发起访问的类”。
- 规则主体要明确主语:想约束“controller不能调service”,就得写
classes().that().resideInAnyPackage("..controller..")作为主语 - 谓语用
should().accessClassesThat().resideInAnyPackage("..service..")才对;反过来写就查反了 - 路径通配符
..代表任意深度子包,*只匹配一级,com.example..比com.example.*更常用也更安全 - 规则默认不递归检查内部类,如有需要加
.and().areNotRecords()等过滤条件,避免误报
CI里ArchUnit测试突然变慢甚至超时?
ArchUnit在首次加载字节码时会解析整个classpath,如果@AnalyzeClasses范围过大(比如扫java..或没设packages),CI机器上可能卡住几十秒。
- 永远显式限定扫描包:
@AnalyzeClasses(packages = "com.mycompany.myapp"),别留空 - 避免在测试里重复创建
JavaClasses对象,提取成static final字段复用 - Gradle中可加
jvmArgs = ["-Xmx1g"]给test任务,防止OOM;Maven则在surefire-plugin里配<argline>-Xmx1g</argline> - ArchUnit 1.2+支持
CacheMode.ENABLED,但仅限同一JVM内多次调用,CI单次运行无效,别白配
规则报错但实际代码没问题?
典型现象:规则说com.myapp.controller.UserController accesses com.myapp.service.UserService,可明明用了FeignClient或DTO做隔离——其实是ArchUnit把编译生成的桥接方法、Lombok的$accessor、或Spring代理类也算进调用了。
立即学习“Java免费学习笔记(深入)”;
- 加过滤:在规则末尾链式调用
.because("avoid Lombok/Spring proxy noise"),再用.ignoreDependency(...)排除已知干扰源 - 检查是否误扫了test包:
@AnalyzeClasses的packages参数没排除**.test.**,导致测试代码里的Mock调用也被分析 - Spring Boot应用里,
@Autowired字段注入会被识别为“access”,但构造器注入不会——规则要适配团队实际DI方式,别一刀切
ArchUnit的约束力不在语法多炫,而在规则是否贴合真实分层意图。扫哪个包、忽略哪些合成元素、怎么和Spring代理共存——这些细节定不下来,规则就只是个会响的警报器。










