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

如何编写ArchUnit规则校验@SpringBootApplication类的多项规范

如何编写ArchUnit规则校验@SpringBootApplication类的多项规范

我来帮你把剩下的ArchUnit规则补全,刚好能覆盖你提到的所有校验点!咱们一步步拆解每个要求,最后整合出完整的测试规则。

首先,你已经实现的「类名必须以Application结尾」规则完全没问题,接下来咱们搞定剩下三个核心要求:

1. 确保项目中只有一个@SpringBootApplication类

这个很直接,用haveSize(1)就能校验,只要项目中这类类的数量不是1,测试就会抛出明确的错误。

2. 校验类是public修饰的

ArchUnit提供了现成的断言bePublic(),直接链式调用即可完成校验。

3. 校验类除了标准main方法外无其他内容

这个需要自定义一个ArchCondition做细致检查,要确保:

  • 没有任何字段/常量
  • 没有自定义构造方法(Java自动生成的默认构造可以保留,毕竟普通类无法完全移除默认构造)
  • 只有一个方法,且这个方法是标准的public static void main(String[] args)

先写这个自定义条件:

private static final ArchCondition<JavaClass> ONLY_HAVE_VALID_MAIN_METHOD = new ArchCondition<>("only contain one public static void main method (with String[] args) and no other custom members") {
    @Override
    public void check(JavaClass javaClass, ConditionEvents events) {
        // 检查是否存在字段/常量
        if (!javaClass.getFields().isEmpty()) {
            events.add(SimpleConditionEvent.violated(
                javaClass, 
                javaClass.getName() + " contains unexpected fields: " + javaClass.getFields()
            ));
        }

        // 检查是否存在自定义构造方法(排除Java自动生成的默认构造)
        long customConstructors = javaClass.getConstructors().stream()
                .filter(constructor -> !constructor.isDefaultConstructor())
                .count();
        if (customConstructors > 0) {
            events.add(SimpleConditionEvent.violated(
                javaClass, 
                javaClass.getName() + " contains custom constructors: " + javaClass.getConstructors()
            ));
        }

        // 检查方法数量和main方法的合法性
        List<JavaMethod> methods = javaClass.getMethods();
        if (methods.size() != 1) {
            events.add(SimpleConditionEvent.violated(
                javaClass, 
                javaClass.getName() + " has " + methods.size() + " methods (expected exactly 1 main method)"
            ));
        } else {
            JavaMethod mainMethod = methods.get(0);
            boolean isValidMain = mainMethod.isPublic()
                    && mainMethod.isStatic()
                    && mainMethod.getReturnType().isVoid()
                    && mainMethod.getName().equals("main")
                    && mainMethod.getParameters().size() == 1
                    && mainMethod.getParameters().get(0).getType().isArray()
                    && mainMethod.getParameters().get(0).getType().getComponentType().getName().equals("java.lang.String");
            
            if (!isValidMain) {
                events.add(SimpleConditionEvent.violated(
                    javaClass, 
                    javaClass.getName() + "'s only method is not a valid public static void main(String[] args)"
                ));
            }
        }
    }
};

整合所有规则的完整测试方法

现在把所有规则串起来,就得到了满足你所有要求的测试:

import com.tngtech.archunit.core.domain.JavaClass;
import com.tngtech.archunit.core.domain.JavaMethod;
import com.tngtech.archunit.core.importer.ImportedClasses;
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;
import org.junit.jupiter.api.Test;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import java.util.List;

@Test
void springBootApplicationClassShouldComplyWithAllSpecifications() {
    ArchRule springBootAppRules = ArchRuleDefinition.classes()
            .that().areAnnotatedWith(SpringBootApplication.class)
            .should()
            .bePublic()
            .andShould().haveNameMatching(".*Application")
            .andShould().haveSize(1)
            .andShould(ONLY_HAVE_VALID_MAIN_METHOD);

    springBootAppRules.check(importedClasses);
}

补充说明

  • 关于默认构造方法:Java会自动为没有显式构造的类生成无参默认构造,所以规则里没有禁止它;如果有特殊要求要严格限制(虽然普通Java类做不到完全移除),可以调整构造方法的检查逻辑。
  • 测试失败时,ArchUnit会输出清晰的错误信息,告诉你具体是哪个类违反了哪条规则,方便快速定位问题。

备注:内容来源于stack exchange,提问作者PatPanda

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.14 09:29:52