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

如何用单个ArchUnit测试同时校验类和方法的事务注解规则?

简化ArchUnit测试的方案

当然可以把这4个测试合并成单个测试,借助ArchUnit的规则组合能力就能实现。下面是具体的实现思路和代码示例:

核心规则拆解与合并

规则1:Spring @Transactional的约束

  • 类层面:被@org.springframework.transaction.annotation.Transactional标注的类,必须同时标注@org.springframework.stereotype.Service
  • 方法层面:被@org.springframework.transaction.annotation.Transactional标注的方法,必须定义在被@Service标注的类中

规则2:禁止使用Jakarta @Transactional

  • 禁止任何类标注@jakarta.transaction.Transactional
  • 禁止任何方法标注@jakarta.transaction.Transactional

将以上4项子规则通过ArchRuleDefinition.allOf()组合,即可在单个测试中完成全部校验:

import com.tngtech.archunit.core.domain.JavaClasses;
import com.tngtech.archunit.core.importer.ClassFileImporter;
import com.tngtech.archunit.lang.ArchRule;
import com.tngtech.archunit.lang.syntax.ArchRuleDefinition;
import org.junit.jupiter.api.Test;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import static com.tngtech.archunit.lang.conditions.ArchConditions.alwaysFalse;
import static com.tngtech.archunit.lang.syntax.ConditionPredicates.describedAs;

class TransactionalArchRulesTest {

    // 替换为你要扫描的基础包路径
    private static final JavaClasses CLASSES = new ClassFileImporter().importPackages("your.app.base.package");

    @Test
    void enforceAllTransactionalRules() {
        // Spring @Transactional类的约束
        ArchRule springTxClassRule = ArchRuleDefinition.classes()
                .that().areAnnotatedWith(Transactional.class)
                .should().beAnnotatedWith(Service.class);

        // Spring @Transactional方法的约束
        ArchRule springTxMethodRule = ArchRuleDefinition.methods()
                .that().areAnnotatedWith(Transactional.class)
                .should().beDeclaredInClassesThat().areAnnotatedWith(Service.class);

        // 禁止类使用Jakarta @Transactional
        ArchRule forbidJakartaTxClassRule = ArchRuleDefinition.classes()
                .that().areAnnotatedWith(jakarta.transaction.Transactional.class)
                .should(describedAs("not use jakarta.transaction.Transactional annotation"), alwaysFalse());

        // 禁止方法使用Jakarta @Transactional
        ArchRule forbidJakartaTxMethodRule = ArchRuleDefinition.methods()
                .that().areAnnotatedWith(jakarta.transaction.Transactional.class)
                .should(describedAs("not use jakarta.transaction.Transactional annotation"), alwaysFalse());

        // 组合所有规则并执行校验
        ArchRule combinedRule = ArchRuleDefinition.allOf(
                springTxClassRule,
                springTxMethodRule,
                forbidJakartaTxClassRule,
                forbidJakartaTxMethodRule
        );

        combinedRule.check(CLASSES);
    }
}

这样单个测试就能覆盖所有要求的校验逻辑,若有规则违反,测试会清晰标注是类还是方法层面的问题,便于快速定位。

内容的提问来源于stack exchange,提问作者Dónal

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.16 13:51:02