如何用ArchUnit测试调用Hello类A方法的代码必须调用B方法?
用ArchUnit验证调用Hello类A方法的代码必须同时调用B方法
问题需求
需要编写测试规则:所有调用第三方库中Hello类A()方法的代码,必须同时调用该类的B()方法(调用顺序不做要求)。已完成部分ArchUnit代码,需实现callsBMethod()谓词。
现有代码示例
Hello类定义
class Hello { void A() {...} void B() {...} void C() {...} }
测试用例代码
Hello hello1 = new Hello(); hello1.A(); // 违反规则:仅调用A(),未调用B(),测试失败 Hello hello2 = new Hello(); hello2.A(); hello2.B(); // 符合规则:同时调用A()和B(),测试成功
未完成的ArchUnit规则
ArchRuleDefinition.methods().that().areDeclaredIn(Hello.class) .and().haveName("A") .should().onlyBeCalled().byCodeUnitsThat(<callsBMethod()>)
实现方案
可以通过ArchUnit的CodeUnit谓词API实现callsBMethod()逻辑,核心是检查调用A()的代码单元(方法)是否也包含对Hello.B()的调用。
完整的ArchUnit规则代码
import com.tngtech.archunit.core.domain.JavaCodeUnit; import com.tngtech.archunit.lang.ArchCondition; import com.tngtech.archunit.lang.ConditionEvents; import com.tngtech.archunit.lang.SimpleConditionEvent; import com.tngtech.archunit.lang.syntax.ArchRuleDefinition; // 定义谓词:检查代码单元是否调用了Hello.B() ArchCondition<JavaCodeUnit> callsBMethod = new ArchCondition<>("call Hello.B()") { @Override public void check(JavaCodeUnit codeUnit, ConditionEvents events) { boolean callsB = codeUnit.getMethodCallsFromSelf().stream() .anyMatch(call -> call.getTarget().getOwner().isEquivalentTo(Hello.class) && call.getTarget().getName().equals("B")); if (!callsB) { events.add(SimpleConditionEvent.violated(codeUnit, String.format("Method %s calls Hello.A() but does NOT call Hello.B()", codeUnit.getFullName()))); } } }; // 完整规则 ArchRuleDefinition.methods() .that().areDeclaredIn(Hello.class) .and().haveName("A") .should().onlyBeCalled().byCodeUnitsThat(callsBMethod);
逻辑说明
- 自定义
ArchCondition实现callsBMethod,遍历代码单元的所有方法调用,判断是否存在对Hello.B()的调用 - 若调用
Hello.A()的方法未调用Hello.B(),则触发违规事件,输出明确的错误信息 - 规则生效后,示例中的
hello1代码所在方法会被检测为违规,hello2所在方法会通过检测
内容的提问来源于stack exchange,提问作者kamer
相关产品推荐
相关产品推荐

