如何用ArchUnit编写JUnit测试检测Spring Boot Kotlin项目的反射使用?
用ArchUnit检测Spring Boot Kotlin项目中的反射使用
这个需求完全可行,ArchUnit通过字节码分析可以轻松检测代码中的反射调用,以下是具体实现方案:
1. 添加ArchUnit依赖
在你的Gradle或Maven配置中加入ArchUnit的JUnit 5依赖(以Gradle Kotlin DSL为例):
testImplementation("com.tngtech.archunit:archunit-junit5:1.2.1") testImplementation("com.tngtech.archunit:archunit-core:1.2.1")
2. 编写JUnit测试用例
核心是通过ArchUnit的规则,禁止项目代码调用Java或Kotlin的反射API。下面是完整的测试类示例:
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.noClasses import org.junit.jupiter.api.Test class ReflectionUsageCheckTest { // 导入你项目的根包,替换成实际路径 private val projectClasses: JavaClasses = ClassFileImporter().importPackages("com.your.project.root") @Test fun `禁止使用Java反射API`() { val javaReflectionRule: ArchRule = noClasses() // 禁止调用Class类的反射相关方法 .should().callMethodOn(Class::class.java) .withNameMatching("forName|getMethod|getDeclaredMethod|getField|getDeclaredField|getConstructor|getDeclaredConstructor") // 禁止调用Method/Field/Constructor的反射执行方法 .orShould().callMethodOnAnyOf( java.lang.reflect.Method::class.java, java.lang.reflect.Field::class.java, java.lang.reflect.Constructor::class.java ) .withNameMatching("invoke|get|set|newInstance") javaReflectionRule.check(projectClasses) } @Test fun `禁止使用Kotlin反射API`() { val kotlinReflectionRule: ArchRule = noClasses() // 禁止访问kotlin.reflect包下的类或调用其中的方法 .should().accessClassesThat().resideInAPackage("kotlin.reflect..") .orShould().callMethodOnClassesThat().resideInAPackage("kotlin.reflect..") kotlinReflectionRule.check(projectClasses) } }
3. 自定义规则(可选)
如果有某些类或包需要允许使用反射(比如特定的配置类),可以通过that()和doNot...来排除:
// 排除名为ReflectionAllowedConfig的类 val rule: ArchRule = noClasses() .that().doNotHaveSimpleName("ReflectionAllowedConfig") .should().callMethodOn(Class::class.java) .withNameMatching("forName")
或者排除整个包:
// 允许com.your.project.allowed包下的类使用反射 val rule: ArchRule = noClasses() .that().resideOutsideOfPackage("com.your.project.allowed..") .should().callMethodOn(Class::class.java) .withNameMatching("forName")
注意事项
- 确保导入的是你项目的根包,这样ArchUnit只会扫描你自己编写的代码,不会检测Spring框架等第三方依赖中的反射使用。
- 可以根据实际需求调整规则中的方法名匹配,比如添加更多反射相关方法的名称。
内容的提问来源于stack exchange,提问作者Abhi
相关产品推荐
相关产品推荐

