skipTests 只是止痛药,病根多在这四处
项目引入org.junit.Test写单测之后,无论mvn package还是mvn install,都报这样一段错:
Failed to execute goal org.apache.maven.plugins:maven-surefire-plugin:2.22.2:test (default-test) on project xxx: There are test failures. Please refer to .../target/surefire-reports for the individual test results.很多人的第一反应是搜“怎么跳过测试”,然后在 pom 里加上skipTests。报错消失,皆大欢喜。
但我的观点是:**这条报错的意思不是 Maven 坏了,而是“测试跑了,而且失败了”。**直接跳过,等于把报警器拆掉,问题还在原地。正确的顺序是:先读报告,修病因,实在要跳再跳,而且要跳得有节制。
01第一步:读懂报错,去看报告
报错里已经告诉你该去哪看:target/surefire-reports。里面有每个测试类的.txt和.xml报告,打开失败的那个,看第一个异常和它的Caused by。也可以只运行失败的测试,缩小范围:
mvn test -Dtest=CouponApplicationTests提示里提到的 dump 文件,通常只在 JVM 异常退出时才有,大多数情况下没有,不必在意。
02四类最常见的病根
| 病根 | 典型症状 | 怎么处理 |
|---|---|---|
| Spring 上下文加载失败 | 报告里出现Failed to load ApplicationContext、连不上数据库、Nacos、Redis 等 | 测试环境提供依赖,或用@MockBean、测试专用配置替代外部依赖;真要连外部服务的测试,单独归为集成测试 |
| JUnit 4 与 JUnit 5 混用 | @Autowired为 null、测试没被执行或直接报错 | 统一框架,见下一节 |
| 环境差异 | Windows 路径、编码、端口被占用、时区不一致 | 不要写死本机路径和端口,用相对路径或随机端口 |
| 断言真的不成立 | AssertionError、期望值与实际值不符 | 这是好事,说明测试在起作用,去修代码或修测试 |
03引入 org.junit.Test 时,最容易踩的暗坑:JUnit 4/5 混用
org.junit.Test是 JUnit 4 的注解。而较新版本的 Spring Boot(2.2 及以后)里,spring-boot-starter-test默认使用的是 JUnit 5,它的注解是org.junit.jupiter.api.Test。两套体系的注解、运行器和扩展方式都不一样,混着用就会出各种怪问题。有两种干净的做法:
**做法一(推荐)**统一用 JUnit 5:导入org.junit.jupiter.api.Test,在 Spring 测试类上只需要@SpringBootTest,不再写@RunWith。
做法二必须保留 JUnit 4 的旧测试,就加上 vintage 引擎,并在 Spring 测试类上使用@RunWith(SpringRunner.class)。
<!-- 做法二:让 JUnit 5 平台也能跑 JUnit 4 的测试 --> <dependency> <groupId>org.junit.vintage</groupId> <artifactId>junit-vintage-engine</artifactId> <scope>test</scope> </dependency>具体版本以你项目的 Spring Boot 版本为准。
04实在要跳:skipTests 可以用,但别写死进 pom
原文的做法是在 pom 里给 surefire 插件配置<skipTests>true</skipTests>。它有效,但问题是:一旦写进 pom,所有人、所有环境(包括 CI)都永久跳过了测试,没人再会发现测试坏了。我的建议是改用命令行临时跳过:
# 跳过运行测试,但仍编译测试代码(推荐) mvn clean package -DskipTests # 连测试代码也不编译(测试代码本身有编译错误时才用) mvn clean package -Dmaven.test.skip=true # 测试仍会运行并报告,但失败不阻断构建 mvn clean package -Dmaven.test.failure.ignore=true取本地赶时间打包时,用命令行参数临时跳过,用完即走。
舍别把 skipTests 当作永久方案写进 pom;CI 流水线里也应该让测试真跑起来。
05原文“场景一”其实不对症
原文的场景一,建议把skip_maven_deploy置为true。这是 Dubbo 项目自己 pom 里用来控制“部署”环节的属性,管的是deploy,而不是 surefire 的测试。本文这类There are test failures的报错,改它不会有任何作用。如果你的报错确实来自 Dubbo 的 deploy 环节,那是另一个问题,需要单独看对应的报错信息,别混在一起处理。
06一个更长远的做法:把单元测试和集成测试分开
很多“打包就失败”的根源,是把需要连数据库、注册中心的集成测试,和纯逻辑的单元测试混在一起,一起在package阶段运行。更好的做法是分层:
单元测试不依赖外部服务,速度快,在package阶段运行,必须通过。
集成测试依赖外部环境,用独立命名(如*IT)或标签区分,在单独的流水线阶段,或通过 Failsafe 插件、Maven Profile 来运行。
一句话总结:**“There are test failures”是在告诉你测试没通过,而不是让你去找跳过测试的办法。**先读报告,再按四类病根逐个排查;确实要跳过,用命令行临时跳,别把它写死进 pom。
说明:插件版本与命令参数以你使用的 Maven、Surefire 和 Spring Boot 版本为准。