Spring项目跨模块运行Cucumber集成测试失败排查
问题:Spring+Cucumber集成测试配置错误,无法找到并运行测试
项目结构
├── src │ ├── integrationTest │ │ ├── java │ │ │ ├── foo.bar.cuke.project │ │ │ │ ├── controller │ │ │ │ │ ├── TestControllerIT.java │ │ │ │ ├── CucumberSpringConfiguration.java │ │ │ │ ├── CucumberTest.java │ │ ├── resources │ │ │ ├── features │ │ │ │ ├── test.feature │ │ │ ├── junit-platform.properties │ ├── main │ ├── test
各文件内容
CucumberSpringConfiguration.java
@SpringBootTest(webEnvironment=SpringBootTest.WebEnvironment.RANDOM_PORT) @CucumberContextConfiguration public class CucumberSpringConfiguration { @Autowired protected TestRestTemplate testRestTemplate; }
CucumberTest.java
@Suite @SelectClasspathResource("src/integrationTest/resources/features") public class CucumberTest { }
TestControllerIT.java
public class TestControllerIT extends CucumberSpringConfiguration { @Given("random given text") public void testGiven() { System.out.println("test"); } }
test.feature
Feature: This is a test feature Scenario: Test scenario Given random given text When a condition is met Then do something
junit-platform.properties
cucumber.plugin=junit:target/cucumber-reports/cucumber.xml cucumber.glue=foo.bar.cuke.project.controller
运行错误
直接运行feature文件时
Suppressed: java.lang.SecurityException: class "org.bouncycastle.jcajce.provider.asymmetric.edec.KeyFactorySpi$Ed448"'s signer information does not match signer information of other classes in the same package at java.base/java.lang.ClassLoader.checkCerts(ClassLoader.java:1156) at java.base/java.lang.ClassLoader.preDefineClass(ClassLoader.java:911) at java.base/java.lang.ClassLoader.defineClass(ClassLoader.java:1020) at java.base/java.security.SecureClassLoader.defineClass(SecureClassLoader.java:174) at java.base/jdk.internal.loader.BuiltinClassLoader.defineClass(BuiltinClassLoader.java:800) at java.base/jdk.internal.loader.BuiltinClassLoader.findClassOnClassPathOrNull(BuiltinClassLoader.java:698) at java.base/jdk.internal.loader.BuiltinClassLoader.loadClassOrNull(BuiltinClassLoader.java:621) at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:579) at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:178)
运行CucumberTest类时
> Task :integrationTest 0 passing (1.9s) > Task :integrationTest FAILED FAILURE: Build failed with an exception. * What went wrong: Execution failed for task ':integrationTest'. > No tests found for given includes: [foo.bar.cuke.project.CucumberTest](--tests filter)
技术栈
- Java 11
- Spring framework 5.3
- JUnit 5
- Cucumber 7.18
- Gradle 7.3
已尝试的解决方法
- 在
build.gradle中添加testSets配置,无效:
testSets { integrationTest } test { systemProperty 'server.ssl.enabled', false }
- 将控制器集成测试类移到
StepDefintions目录下,无效。
核心问题
配置存在哪些问题?为何Cucumber无法找到集成测试文件并运行?
解决方案
1. 修复Gradle集成测试配置
testSets是旧版Gradle语法,Gradle 7.x需用标准Source Set配置识别integrationTest目录,修改build.gradle:
plugins { id 'java' id 'org.springframework.boot' version '2.7.x' // 匹配Spring 5.3的Boot版本 id 'io.spring.dependency-management' version '1.0.15.RELEASE' } // 配置集成测试Source Set sourceSets { integrationTest { java { compileClasspath += main.output + test.output runtimeClasspath += main.output + test.output srcDir file('src/integrationTest/java') } resources { srcDir file('src/integrationTest/resources') } } } // 创建集成测试任务 task integrationTest(type: Test) { description = '运行集成测试' group = 'Verification' testClassesDirs = sourceSets.integrationTest.output.classesDirs classpath = sourceSets.integrationTest.runtimeClasspath useJUnitPlatform() // 启用JUnit 5平台适配Cucumber 7.x // 分离测试报告与单元测试 reports { html.outputLocation = file("$buildDir/reports/integrationTests") junitXml.outputLocation = file("$buildDir/test-results/integrationTests") } } check.dependsOn integrationTest // 依赖配置 dependencies { // 主项目依赖... // 单元测试依赖... // 集成测试专属依赖 integrationTestImplementation 'io.cucumber:cucumber-java:7.18.0' integrationTestImplementation 'io.cucumber:cucumber-spring:7.18.0' integrationTestImplementation 'io.cucumber:cucumber-junit-platform-engine:7.18.0' integrationTestImplementation 'org.springframework.boot:spring-boot-starter-test' integrationTestImplementation 'org.junit.platform:junit-platform-suite-api:1.9.3' integrationTestRuntimeOnly 'org.junit.platform:junit-platform-launcher:1.9.3' }
2. 修正CucumberTest的路径配置
@SelectClasspathResource参数是类路径资源路径,不是文件系统路径。src/integrationTest/resources会被编译到类路径根目录,所以修改为:
@Suite @SelectClasspathResource("features") // 直接指向类路径下的features目录 // 可选:在这里指定glue,替代junit-platform.properties的配置 @ConfigurationParameter(key = GLUE_PROPERTY_NAME, value = "foo.bar.cuke.project") public class CucumberTest { }
3. 解决BouncyCastle签名冲突
运行feature文件的SecurityException是因为多个版本的BouncyCastle库签名不一致,在build.gradle中统一版本并排除冲突依赖:
configurations.all { resolutionStrategy { force 'org.bouncycastle:bcprov-jdk15on:1.70' // 指定统一版本 exclude group: 'org.bouncycastle', module: 'bcprov-jdk15to18' // 排除冲突版本 } }
4. 补全步骤定义
feature文件中的When和Then步骤无对应实现,运行会报错,补充TestControllerIT代码:
public class TestControllerIT extends CucumberSpringConfiguration { @Given("random given text") public void testGiven() { System.out.println("test"); } @When("a condition is met") public void aConditionIsMet() { // 实现业务逻辑 } @Then("do something") public void doSomething() { // 实现断言或验证逻辑 } }
正确运行方式
- 命令行:执行
./gradlew integrationTest - IntelliJ:直接运行
CucumberTest类,或右键Gradle面板的integrationTest任务运行
内容的提问来源于stack exchange,提问作者Samuel Alito
相关产品推荐
相关产品推荐

