Spring Boot+Maven独立单元测试框架搭建及代码覆盖率检查问题求助
我来帮你搞定这个拆分业务代码和测试代码的问题——之前的方案踩坑大概率是因为Spring Boot默认打包的是可执行Jar,结构和普通Maven Jar不一样,导致测试项目没法正确依赖业务类。下面是一套亲测有效的方案,一步步来:
我们的目标是让两个项目完全独立:一个只放业务代码,生成普通的Maven业务Jar;另一个只放单元测试代码,依赖这个业务Jar来执行测试,同时用Jacoco统计业务代码的覆盖率。这样既保持了代码整洁,又能正常跑测试和看覆盖率。
Spring Boot默认的spring-boot-maven-plugin会把项目打包成可执行Jar,里面的类都在BOOT-INF/classes目录下,测试项目依赖的时候根本找不到这些类。所以我们要修改业务项目的pom.xml,让它同时生成普通业务Jar和可执行Spring Boot Jar:
<!-- 打包类型保持为jar --> <packaging>jar</packaging> <!-- 如果之前用spring-boot-starter-parent作为父项目,保留即可;如果不想用父项目,就用dependencyManagement导入Spring Boot依赖 --> <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-dependencies</artifactId> <version>你的Spring Boot版本</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> <version>你的Spring Boot版本</version> <executions> <execution> <goals> <goal>repackage</goal> </goals> <configuration> <!-- 给可执行Jar加个classifier,这样会生成两个Jar:xxx.jar(普通业务Jar)和xxx-exec.jar(可执行Jar) --> <classifier>exec</classifier> </configuration> </execution> </executions> </plugin> </plugins> </build>
修改完后,执行mvn clean install,就能在业务项目的target目录下看到两个Jar,我们的测试项目只需要依赖那个不带-exec后缀的普通Jar。
新建一个Maven项目(不需要是Spring Boot项目,当然你也可以建Spring Boot项目,只要精简依赖就行),然后在pom.xml里配置依赖和插件:
<dependencies> <!-- 依赖你的业务项目 --> <dependency> <groupId>你的业务项目groupId</groupId> <artifactId>你的业务项目artifactId</artifactId> <version>对应版本号</version> <scope>test</scope> </dependency> <!-- TestNG测试框架依赖 --> <dependency> <groupId>org.testng</groupId> <artifactId>testng</artifactId> <version>7.8.0</version> <scope>test</scope> </dependency> <!-- Spring Test支持,用来测试Spring组件(比如Service、Controller) --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <version>你的Spring Boot版本</version> <scope>test</scope> <!-- 如果只用TestNG,排除JUnit相关依赖避免冲突 --> <exclusions> <exclusion> <groupId>org.junit.jupiter</groupId> <artifactId>junit-jupiter-api</artifactId> </exclusion> </exclusions> </dependency> </dependencies> <build> <plugins> <!-- TestNG执行插件,指定测试套件配置文件 --> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-surefire-plugin</artifactId> <version>3.2.5</version> <configuration> <suiteXmlFiles> <suiteXmlFile>src/test/resources/testng.xml</suiteXmlFile> </suiteXmlFiles> </configuration> </plugin> <!-- Jacoco插件,生成代码覆盖率报告 --> <plugin> <groupId>org.jacoco</groupId> <artifactId>jacoco-maven-plugin</artifactId> <version>0.8.10</version> <executions> <execution> <id>prepare-agent</id> <goals> <goal>prepare-agent</goal> </goals> </execution> <execution> <id>report</id> <goals> <goal>report</goal> </goals> <configuration> <!-- 关键!指定业务项目编译后的class文件路径,Jacoco才能分析业务代码的覆盖率 --> <classesDirectory>${project.basedir}/../业务项目名称/target/classes</classesDirectory> </configuration> </execution> </executions> </plugin> </plugins> </build>
注意:classesDirectory的路径要根据你的项目实际位置调整,如果业务项目和测试项目是同级目录,用上面的相对路径就行;如果是其他结构,改成对应的绝对路径或者正确的相对路径。
在Jenkins里新建一个流水线或者自由风格项目,按以下顺序执行:
- 拉取业务代码项目,执行
mvn clean install——把业务Jar安装到本地仓库(如果是团队协作,建议传到公司的Maven私服) - 拉取测试代码项目,执行
mvn clean test jacoco:report——运行TestNG测试并生成Jacoco覆盖率报告 - 在Jenkins的项目配置里,添加「Jacoco插件」的配置,指向测试项目
target/site/jacoco目录下的报告文件,这样就能在Jenkins界面直接查看覆盖率统计了
- 找不到业务类:检查业务项目是否生成了普通Jar,测试项目的依赖
groupId、artifactId、version是否完全匹配,scope是否设为test(如果测试代码在编译阶段就需要依赖,改成compile) - Spring Bean无法注入:在测试类上添加
@SpringBootTest(classes = 业务项目的启动类.class),确保Spring上下文能正确加载业务项目的所有Bean - Jacoco覆盖率为0:检查
classesDirectory是否正确指向业务项目的target/classes目录,同时确认测试代码确实覆盖了业务类的方法(可以先跑单个测试看看有没有生效)
内容的提问来源于stack exchange,提问作者Maidi Gu

