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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.18 03:47:02