Spring Boot集成测试的Maven插件配置困惑:Failsafe还是Surefire?
你遇到的这个困惑其实非常普遍——Spring Boot官方示例和Maven的传统约定好像“打架”了,我来帮你理清楚这里面的逻辑:
1. 先搞懂两个插件的本质区别
Maven的maven-surefire-plugin和maven-failsafe-plugin不是Spring Boot发明的,是Maven生态里的标准分工:
- Surefire:负责快速执行单元测试——这类测试一般不依赖外部服务、数据库,只测单个类/方法,速度快,应该在构建早期执行。默认匹配
*Test.java。 - Failsafe:负责执行集成测试——这类测试需要启动Spring上下文、连接数据库/外部服务,速度慢,通常在构建的后期(比如打包后)执行,而且允许失败后继续构建(方便排查问题)。默认匹配
*IT.java。
2. 为什么Spring Boot官方示例都用Test后缀?
其实Spring Boot本身不区分单元测试和集成测试——不管你用@SpringBootTest还是普通@Test,它只是提供测试支持框架。官方示例这么做,更多是为了简化演示,让读者不用额外配置插件就能直接运行测试,没严格遵循Maven的插件分工约定。
3. 你的做法和同事的做法,谁对谁错?
其实没有绝对的“对错”,只有场景差异:
你的做法(*IT.java + Failsafe)
这是符合Maven标准约定的正确做法,好处非常明显:
- 可以单独执行集成测试(比如
mvn verify只跑集成测试,mvn test只跑单元测试); - 集成测试失败不会中断早期的构建流程;
- 单元和集成测试的职责清晰,便于维护。
但你遇到的Sonar覆盖率问题,确实是因为Failsafe的测试结果默认不会被Cobertura自动捕获。解决方法很简单,需要在Cobertura插件里额外配置,让它包含集成测试的类和结果:
<plugin> <groupId>org.codehaus.mojo</groupId> <artifactId>cobertura-maven-plugin</artifactId> <version>2.7</version> <executions> <execution> <id>cobertura-integration</id> <goals> <goal>cobertura</goal> </goals> <phase>verify</phase> <configuration> <instrumentation> <includes> <include>**/*IT.java</include> </includes> </instrumentation> <formats> <format>xml</format> </formats> </configuration> </execution> </executions> </plugin>
同时在Sonar的配置里指定Failsafe的测试报告路径:
<properties> <sonar.junit.reportPaths>${project.build.directory}/failsafe-reports</sonar.junit.reportPaths> </properties>
同事的做法(*Test.java + Surefire)
这种做法把所有测试(单元+集成)都丢给Surefire执行,好处是不用额外配置插件,Sonar默认就能读取Surefire的测试结果,所以覆盖率能正常显示。但缺点也很突出:
- 单元测试和集成测试混在一起,没法单独执行某一类;
- 集成测试速度慢,会拖慢整个
mvn test的构建时间; - 不符合Maven的标准约定,团队新人容易混淆测试职责。
4. 关于Spring Boot Maven插件文档的疑惑
Spring Boot Maven插件本身不强制你使用哪个测试插件,它只是兼容Maven的标准生态。文档里提到Failsafe,是因为那是Maven社区公认的集成测试插件,所以在“跳过集成测试”的场景下,自然会提到它——这并不意味着Spring Boot推荐或不推荐,只是告诉你怎么和Maven的标准工具配合。
最后给你的建议
如果你的项目规模较大,集成测试数量多,强烈建议坚持你的做法——符合Maven约定,职责清晰,长远来看更利于维护,只要花点时间把Cobertura和Sonar的配置补全就行。如果项目很小,测试数量少,团队统一的话,用同事的做法也能接受,但要注意后续的扩展性。
内容的提问来源于stack exchange,提问作者Dherik

