1. 概述

在日常开发中,我们经常使用 Maven 构建项目并生成可执行的 Jar 包。默认情况下,Maven 在执行 package 阶段时会自动运行单元测试,只有所有测试通过,构建才会成功

但有时候我们会遇到一些特殊情况:

✅ 测试本身有问题,短期内无法修复
✅ 第三方依赖不稳定导致测试偶发失败
✅ 需要紧急打包发布,先绕过测试

这时,我们就需要一种方式:构建 Jar 包,但忽略测试结果或跳过测试执行。本文将介绍几种简单粗暴又实用的方法,帮你绕过这些“踩坑”场景。


2. 项目构建与测试失败的影响

我们先来看一个简单的例子。假设项目中有一个测试类:

public class TestFail {
    @Test
    public void whenMessageAssigned_thenItIsNotNull() {
        String message = "hello there";
        assertNotNull(message);
    }
}

执行标准构建命令:

mvn package

Maven 会完成以下动作:

  • 编译源码
  • 编译测试代码
  • 运行单元测试
  • 打包生成 target/maven-0.0.1-SNAPSHOT.jar

一切正常时,构建成功,Jar 包顺利生成。

但现在我们故意让测试失败:

@Test
public void whenMessageAssigned_thenItIsNotNull() {
    String message = null;
    assertNotNull(message); // 这里会抛 AssertionError
}

再次执行 mvn package,你会发现:

❌ 构建失败(BUILD FAILURE)
❌ Jar 包未生成
❌ 控制台报错:There are test failures.

这就带来一个问题:即使主程序逻辑没问题,只要有一个测试失败,就无法出包。在某些紧急场景下,这显然不够灵活。


3. 使用 Maven 命令行参数控制测试行为

Maven 提供了多个内置参数,可以灵活控制测试的编译与执行行为。以下是几个关键参数,建议集合:

参数 作用 是否编译测试 是否运行测试 失败是否影响构建
-Dmaven.test.skip=true 完全跳过测试 ❌ 不编译 ❌ 不运行 ❌ 无影响
-Dmaven.test.failure.ignore=true 允许测试失败 ✅ 编译 ✅ 运行 ✅ 构建仍成功
-fn-fae fail-never / fail-at-end ✅ 编译 ✅ 运行 ✅ 构建成功

3.1 跳过测试编译与执行

mvn package -Dmaven.test.skip=true

输出示例:

[INFO] Tests are skipped.
[INFO] BUILD SUCCESS

⚠️ 注意:这个参数不仅跳过测试运行,连测试类都不编译。适合完全不想碰测试的场景。


3.2 忽略测试失败

mvn package -Dmaven.test.failure.ignore=true

输出示例:

[INFO] Running testfail.TestFail
[ERROR] whenMessageAssigned_thenItIsNotNull java.lang.AssertionError
[INFO] BUILD SUCCESS

✅ 测试运行了,也报错了,但构建仍然成功,Jar 包正常生成。


3.3 使用 -fn-fae 参数

mvn package -fn
# 或
mvn package -fae

这两个参数效果类似,都是“即使测试失败也不中断构建”。

区别在于:

  • -fae(fail-at-end):运行完所有测试后才报告失败,但仍标记为成功
  • -fn(fail-never):更激进,根本不关心失败

⚠️ 在多模块项目中建议使用 -fn。因为 -fae 虽然会运行当前模块的测试,但一旦失败,会跳过所有依赖该模块的后续模块构建,容易导致漏打包。


4. 使用 Maven Surefire 插件配置

除了命令行参数,我们也可以在 pom.xml 中通过配置 Maven Surefire Plugin 来控制测试行为。这种方式更适合需要长期生效的场景。

4.1 忽略测试失败

<plugin>
    <artifactId>maven-surefire-plugin</artifactId>
    <version>${maven.surefire.version}</version>
    <configuration>
        <includes>
            <include>TestFail.java</include>
        </includes>
        <testFailureIgnore>true</testFailureIgnore>
    </configuration>
</plugin>

配置后,执行 mvn package,输出如下:

[INFO]  T E S T S
[INFO] Running testfail.TestFail
[ERROR] Tests run: 1, Failures: 1, Errors: 0, Skipped: 0, <<< FAILURE! - in testfail.TestFail
...
[INFO] BUILD SUCCESS

✅ 测试失败被记录,但构建成功,Jar 包正常生成。


4.2 完全跳过测试执行

如果你希望编译测试类但不运行,可以使用:

<plugin>
    <artifactId>maven-surefire-plugin</artifactId>
    <version>${maven.surefire.version}</version>
    <configuration>
        <skipTests>true</skipTests>
    </configuration>
</plugin>

等价于命令行参数:

mvn package -DskipTests

区别:

  • -Dmaven.test.skip=true:不编译也不运行
  • -DskipTests:编译测试类,但不运行

✅ 适用于需要保留测试编译结果(如生成覆盖率报告)但不想运行的场景。


5. 总结

在实际项目中,测试是保障质量的重要手段,但不能因为测试问题阻塞交付。本文介绍了几种在 Maven 中绕过测试限制的方法:

方法 适用场景
-Dmaven.test.skip=true 完全不想理测试,快速出包
-Dmaven.test.failure.ignore=true 测试要跑,但失败无所谓
-fn / -fae 多模块项目中确保构建不中断
Surefire 插件配置 长期策略,配置化管理

✅ 建议:

  • 临时出包用命令行参数
  • 持久化需求写进 pom.xml

示例代码已托管至 GitHub:https://github.com/dev-example/maven-ignore-test


原始标题:Build a Jar with Maven and Ignore the Test Results