如何基于条件禁用Cucumber Spring中Steps类的实例化?
可以实现类似Spring Boot @ConditionalOnClass 的效果,核心思路是结合Spring的条件Bean定义机制,让Cucumber仅在目标类存在时才加载对应的Steps类。以下是具体方案:
方案一:利用Spring Boot的@ConditionalOnClass(适用于Spring Boot项目)
如果你的项目基于Spring Boot,直接用官方提供的条件注解即可:
调整Steps类的定义
把MySteps改为普通类,放在非Cucumber默认扫描的路径下:class MySteps(val someDep: SomeDep) { @Before fun initialize() { // 依赖SomeDep的初始化逻辑 } }创建条件化的Bean配置
在通用库中添加一个Spring配置类,通过@Bean和@ConditionalOnClass控制MySteps的实例化:@Configuration class ConditionalStepsConfig { @Bean @ConditionalOnClass(SomeDep::class) fun mySteps(someDep: SomeDep): MySteps { return MySteps(someDep) } }确保配置类被Spring扫描
让使用通用库的应用通过@Import(ConditionalStepsConfig::class)或者组件扫描包含该配置类所在的包,Spring会根据类路径是否存在SomeDep来决定是否创建MyStepsBean。
方案二:自定义Spring Condition(兼容非Spring Boot项目)
如果项目不使用Spring Boot,自定义一个Condition类来检查类路径:
实现自定义Condition
class SomeDepPresentCondition : Condition { override fun matches(context: ConditionContext, metadata: AnnotatedTypeMetadata): Boolean { return try { // 检查类路径中是否存在SomeDep context.classLoader.loadClass("com.yourpackage.SomeDep") true } catch (e: ClassNotFoundException) { false } } }配置条件化Bean
把方案一中的@ConditionalOnClass替换为自定义的Condition:@Configuration class ConditionalStepsConfig { @Bean @Conditional(SomeDepPresentCondition::class) fun mySteps(someDep: SomeDep): MySteps { return MySteps(someDep) } }后续步骤同方案一
确保配置类被Spring扫描,Cucumber会自动识别Spring上下文中带有@Before等注解的Bean,只有当MyStepsBean存在时,才会执行对应的钩子逻辑。
关键原理说明
Cucumber Spring的核心机制是:从Spring上下文中获取所有带有Cucumber注解(@Before、@Given等)的Bean,而非直接实例化扫描到的所有Steps类。因此通过Spring的条件Bean定义,就能精准控制MySteps是否被纳入Cucumber的执行流程:
- 当类路径存在
SomeDep时,Spring创建MyStepsBean,Cucumber发现并使用它的钩子 - 当类路径不存在
SomeDep时,MyStepsBean不会被创建,Cucumber不会处理该类,也不会抛出依赖缺失的异常
内容的提问来源于stack exchange,提问作者David Kubecka

