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

基于Maven Surefire配置构建含测试依赖的可执行Uber Jar

解决方案:构建包含Cucumber测试运行器的可执行Uber Jar

核心思路

你的场景需要打包主应用代码、子模块编译产物、测试类、测试依赖四类资源,普通插件要么不支持测试类打包,要么容易触发类冲突(比如Spring Boot自动配置类、Cucumber插件定义)。下面提供两种经过验证的方案,优先适配Spring环境的方案。


方案一:Spring Boot Maven Plugin打包测试代码(推荐)

如果测试运行器基于@SpringBootTest,直接用Spring Boot插件的测试打包能力,它会自动处理Spring环境的依赖和类路径:

  1. 在主模块pom.xml中配置插件:
<build>
    <plugins>
        <!-- 保留原有主应用打包配置,新增测试打包执行 -->
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
            <executions>
                <execution>
                    <id>repackage-tests</id>
                    <goals>
                        <goal>repackage</goal>
                    </goals>
                    <configuration>
                        <classifier>tests</classifier>
                        <!-- 替换为你的Cucumber测试运行器全类名 -->
                        <mainClass>com.example.CucumberTestRunner</mainClass>
                        <includes>
                            <include>
                                <groupId>${project.groupId}</groupId>
                                <artifactId>*</artifactId>
                                <classifier>tests</classifier>
                            </include>
                        </includes>
                    </configuration>
                </execution>
            </executions>
        </plugin>
        <!-- 确保子模块测试类被编译为test-jar供主模块引用 -->
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-jar-plugin</artifactId>
            <executions>
                <execution>
                    <goals>
                        <goal>test-jar</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>
    </plugins>
</build>
  1. 执行打包命令:
mvn clean package

打包完成后会生成[项目名]-tests.jar,直接运行:

java -jar [项目名]-tests.jar

方案二:Shade插件+依赖插件手动处理

如果不依赖Spring Boot插件,手动管控测试类和依赖的打包逻辑:

  1. 配置maven-dependency-plugin导出测试依赖到临时目录:
<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-dependency-plugin</artifactId>
    <executions>
        <execution>
            <id>copy-test-deps</id>
            <phase>prepare-package</phase>
            <goals>
                <goal>copy-dependencies</goal>
            </goals>
            <configuration>
                <outputDirectory>${project.build.directory}/test-libs</outputDirectory>
                <includeScope>test</includeScope>
            </configuration>
        </execution>
    </executions>
</plugin>
  1. 配置maven-shade-plugin合并资源、处理冲突:
<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-shade-plugin</artifactId>
    <version>3.4.1</version>
    <executions>
        <execution>
            <phase>package</phase>
            <goals>
                <goal>shade</goal>
            </goals>
            <configuration>
                <transformers>
                    <!-- 指定测试运行器为主类 -->
                    <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
                        <mainClass>com.example.CucumberTestRunner</mainClass>
                    </transformer>
                    <!-- 合并Spring自动配置文件,避免加载失败 -->
                    <transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
                        <resource>META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports</resource>
                    </transformer>
                    <!-- 合并Cucumber插件定义,避免步骤丢失 -->
                    <transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
                        <resource>META-INF/services/io.cucumber.core.plugin.Plugin</resource>
                    </transformer>
                </transformers>
                <!-- 排除签名文件,避免打包报错 -->
                <filters>
                    <filter>
                        <artifact>*:*</artifact>
                        <excludes>
                            <exclude>META-INF/*.SF</exclude>
                            <exclude>META-INF/*.DSA</exclude>
                            <exclude>META-INF/*.RSA</exclude>
                        </excludes>
                    </filter>
                </filters>
                <!-- 包含主应用、子模块、测试依赖的类 -->
                <artifactSet>
                    <includes>
                        <include>${project.groupId}:</include>
                        <include>io.cucumber:*</include>
                        <include>org.testng:*</include>
                        <include>org.springframework.boot:spring-boot-test*</include>
                    </includes>
                </artifactSet>
                <!-- 引入临时目录的测试依赖 -->
                <additionalClasspathElements>
                    <additionalClasspathElement>${project.build.directory}/test-libs</additionalClasspathElement>
                </additionalClasspathElements>
            </configuration>
        </execution>
    </executions>
</plugin>
  1. 执行打包命令:
mvn clean package

生成的Jar即可直接运行。


常见问题排查

  • 类找不到:检查Shade插件的artifactSet是否包含所有子模块,确保子模块的test-jar被主模块依赖。
  • Cucumber步骤定义丢失:确认测试类被纳入打包范围,可在Shade配置中添加<include>${project.build.testOutputDirectory}</include>。
  • Spring上下文加载失败:检查AutoConfiguration.imports文件是否被正确合并,确保Spring Boot自动配置类能被扫描到。
  • 多线程失效:保持原有TestNG/Cucumber的多线程配置,运行Jar时可通过参数指定:java -jar xxx.jar -Dcucumber.execution.parallel.enabled=true

内容的提问来源于stack exchange,提问作者Paulo Oliveira

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.24 12:43:39