You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

在ArchUnit中能否将方法定义转换为谓词?

问题

我想要编写测试用例,禁止系统内所有类调用外部定义的静态方法(本文中为com.vaadin.flow.internal.StringUtil类的方法)。目前我已通过以下代码实现该需求:

ArchRuleDefinition.noClasses().should().callMethodWhere(
        JavaAccess.Predicates.targetOwner(JavaClass.Predicates
                .assignableTo("com.vaadin.flow.internal.StringUtil")))
        .check(new ClassFileImporter()
                .importPackages("com.example.application"));

不过ArchUnit已提供更简洁的定义方式:

ArchRuleDefinition.methods().that()
                .areDeclaredIn("com.vaadin.flow.internal.StringUtil")

若能将上述定义转换为谓词传入callMethodWhere,比如编写如下形式的代码,可让测试用例更易理解:

ArchRuleDefinition.noClasses().should()
        .callMethodWhere(transformInPredicate(ArchRuleDefinition.methods().that()
                .areDeclaredIn("com.vaadin.flow.internal.StringUtil")))
        .check(new ClassFileImporter()
                .importPackages("com.example.application"));

请问这种转换是否可行?

回答

这种转换完全可行,借助ArchUnit内置的API就能实现,既保留简洁的语义表达,又能提升测试代码的可读性。

具体实现代码

你可以通过asPredicate()将方法规则转换为DescribedPredicate<JavaMethod>,再用JavaAccess.Predicates.target()把它适配为callMethodWhere所需的方法调用判断谓词:

ArchRuleDefinition.noClasses().should()
        .callMethodWhere(JavaAccess.Predicates.target(
                ArchRuleDefinition.methods().that()
                        .areDeclaredIn("com.vaadin.flow.internal.StringUtil")
                        .asPredicate()
        ))
        .check(new ClassFileImporter()
                .importPackages("com.example.application"));

关键逻辑说明

  • asPredicate():将MethodsShouldConjunction类型的方法规则直接转换为判断JavaMethod实例的谓词
  • JavaAccess.Predicates.target():把方法谓词包装成适配方法调用(JavaMethodAccess)的谓词,完美匹配callMethodWhere的参数要求
  • 这种写法既利用了ArchRuleDefinition的简洁语法,又保持了原测试逻辑的正确性

内容的提问来源于stack exchange,提问作者brunovianarezende

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.30 23:00:40