如何用ArchUnit检测Java类中已初始化的指定类型字段?
用ArchUnit检测已初始化的指定类型字段
给定Java类:
public class A { private B b1 = new B(); private C c = new C(); private B b2; }
需求:编写ArchUnit测试,找出类A中类型为B且已完成初始化的字段(即示例中的b1,b2未初始化不会被匹配)。
你提供的未完成测试代码:
@ArchTest void dontInitialize(JavaClasses classesToTest) { noFields().that().haveRawType(DescribedPredicate.describe("that is a B object", type -> { return type.isAssignableTo(B.class); })).should(new ArchCondition<JavaField>("") { @Override public void check(JavaField javaField, ConditionEvents conditionEvents) { // ??? } }); }
这个需求完全可以实现,ArchUnit提供了直接判断字段初始化状态的API,下面是两种实现方式:
方式一:自定义条件(支持精确匹配初始化方式)
@ArchTest void findInitializedBFields(JavaClasses classesToTest) { fields() .that().areDeclaredIn(A.class) .and().haveRawType(B.class) .should(new ArchCondition<JavaField>("be initialized with a new B instance") { @Override public void check(JavaField field, ConditionEvents events) { // 先判断字段是否有初始化表达式 if (field.getInitializer() != null) { // 可选:严格匹配初始化代码为new B() String initCode = field.getInitializer().getSourceCode(); if ("new B()".equals(initCode)) { events.add(SimpleConditionEvent.satisfied(field, field.getName() + " 符合条件:已用new B()初始化")); } } else { events.add(SimpleConditionEvent.violated(field, field.getName() + " 未初始化")); } } }).check(classesToTest); }
方式二:使用ArchUnit内置谓词(简洁版)
如果只需要找出所有类型为B且有初始化的字段,不管具体初始化方式,用内置的haveInitializer()谓词更简洁:
@ArchTest void findInitializedBFieldsSimpler(JavaClasses classesToTest) { fields() .that().areDeclaredIn(A.class) .and().haveRawType(B.class) .and().haveInitializer() .should().exist() // 断言这类字段存在,也可以替换为其他验证逻辑 .check(classesToTest); }
关键说明
field.getInitializer():返回字段的初始化表达式对象,非null则表示字段在声明时已完成初始化getInitializer().getSourceCode():可以获取初始化代码的字符串,用于精确匹配初始化方式- 内置谓词
haveInitializer():直接判断字段是否有初始化表达式,无需自定义条件
内容的提问来源于stack exchange,提问作者SCM
相关产品推荐
相关产品推荐

