运行Cucumber测试时如何初始化Spring @Autowired实例?
看起来你遇到的问题很典型——当用Cucumber CLI(比如gradle cucumber命令)或直接运行feature文件时,Spring的依赖注入失效,但直接运行StepDefinitions类时一切正常。这本质上是因为两种运行方式加载Spring上下文的逻辑不一样,下面给你一步步解决的方案:
核心原因
直接运行StepDefinitions.java时,你用的是SpringJUnit4ClassRunner,它会主动处理@SpringBootTest注解,帮你初始化Spring上下文。但用Cucumber CLI或直接跑feature文件时,是Cucumber自己的执行器在工作,它需要明确知道去哪里找Spring配置和Step定义,如果glue路径配置不对,或者缺少Cucumber识别Spring的注解,就会导致上下文初始化失败,@Autowired的实例自然为null。
具体解决方案
1. 修正Glue路径配置(关键!)
你Gradle任务里的--glue 'steps/rufs'是错误的——Cucumber的glue参数需要的是Java包名(用点分隔),不是文件系统路径。比如你的StepDefinitions类如果在com.yourproject.steps.rufs包下,那glue应该写成com.yourproject.steps.rufs。
另外,还要确保glue路径包含你的Spring主配置类Application.class所在的包(比如com.yourproject),这样Cucumber才能找到Spring的入口。修改后的Gradle cucumber任务args应该是:
args = ['--plugin', 'pretty', '--glue', 'com.yourproject.steps.rufs', // Step定义所在包 '--glue', 'com.yourproject', // Spring主配置类所在包 'src/test/resources/features', '--tags','@rufs']
2. 添加Cucumber Spring上下文配置注解
在你的StepDefinitions类上加上@CucumberContextConfiguration注解(来自io.cucumber.spring包),这个注解是告诉Cucumber:“这个类是我用来配置Spring上下文的入口”。修改后的代码:
import io.cucumber.spring.CucumberContextConfiguration; import org.junit.runner.RunWith; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import org.springframework.test.context.web.WebAppConfiguration; @CucumberContextConfiguration // 新增这个注解 @RunWith(SpringJUnit4ClassRunner.class) @SpringBootTest(classes = Application.class) @WebAppConfiguration public class StepDefinitions{ private static String roll; @Autowired MyService myService; @BeforeClass public static void resetValues() { roll = ""; } @Givet("Jag har rollen {string}") public void getRole(String roll) { assertNotNull(roll); this.roll = roll; myService.useRole(roll); } }
3. 统一Cucumber依赖版本
注意到你手动引入了cucumber-spring-4.7.1.jar,但cucumber-java和cucumber-junit用的是变量cucumberVersion。要确保这三个依赖的版本完全一致,否则会出现依赖冲突,导致Spring集成失效。比如在gradle.build里明确:
def cucumberVersion = '4.7.1' dependencies { compile "io.cucumber:cucumber-spring:$cucumberVersion" // 替换本地jar,用maven仓库的依赖更可靠 testCompile "io.cucumber:cucumber-java:$cucumberVersion" testCompile "io.cucumber:cucumber-junit:$cucumberVersion" // 其他依赖... }
建议不要用本地jar,直接从Maven仓库拉取,避免版本不一致的问题。
4. 验证运行方式
修改完配置后:
- 运行
gradle cucumber命令,检查myService是否正常注入 - 直接运行feature文件时,确保IDE的Cucumber运行配置里的Glue路径也设置成正确的包名(和Gradle里一致)
为什么直接运行StepDefinitions正常?
因为直接运行这个类时,IDE用的是SpringJUnit4ClassRunner,它会按照JUnit+Spring的逻辑加载上下文,完全不经过Cucumber的CLI执行器。而Cucumber自己的执行器需要明确的glue配置和Spring上下文标记,这就是两种场景差异的根源。
内容的提问来源于stack exchange,提问作者Softy_

