当前位置:

首页 > 编程开发 > JUnit 5与TestNG对比:Java测试框架怎么选

JUnit 5与TestNG对比:Java测试框架怎么选

对比JUnit 5与TestNG在单元测试、参数化测试、分组、依赖关系、并行执行、扩展机制和测试套件管理方面的差异,并结合实际Java项目说明如何选择测试框架。

如果是新建的普通 Java 项目,特别是以单元测试为主的 Spring、Spring Boot 或常规后端项目,通常可以优先选择 JUnit 5。    如果测试中大量使用分组、测试方法依赖、XML 套件编排、复杂并行策略或数据驱动场景,TestNG 往往更加直接。    两者都能完成常见 Java 测试任务,所以选择时不能只看“哪个功能更多”,而应该看项目准备怎样组织和执行测试。

下面不单纯罗列功能,而是从实际开发中最容易影响选择的几个问题入手:测试代码怎么写、参数化测试有什么区别、    如何组织测试集、能不能控制执行顺序、并行测试是否方便,以及已有项目是否值得迁移。

一、先理解两者的定位差异

JUnit 5 并不只是一个新的 @Test 注解集合。它由 JUnit Platform、JUnit Jupiter 等部分组成。    开发者平时编写 JUnit 5 测试,主要使用的是 Jupiter 编程模型;底层 Platform 则负责发现和启动测试。

TestNG 的思路更偏向一个完整的测试执行框架。除了普通单元测试,它把测试分组、参数传递、方法依赖、    DataProvider、Suite 和并行执行等能力直接放进自己的测试模型中,因此在集成测试、接口测试和较复杂的自动化测试套件中比较方便。

JUnit 5与TestNG对比:Java测试框架怎么选
图1:JUnit 5 与 TestNG 的定位差异,真正需要比较的是测试如何被组织和执行。

二、最基本的测试代码其实差别不大

假设有一个非常简单的价格计算类:

public class PriceCalculator {

    public int add(int price, int shipping) {
        return price + shipping;
    }
}

使用 JUnit 5

import org.junit.jupiter.api.Test;

import static org.junit.jupiter.api.Assertions.assertEquals;

class PriceCalculatorTest {

    @Test
    void shouldAddPriceAndShipping() {
        PriceCalculator calculator = new PriceCalculator();

        int result = calculator.add(100, 20);

        assertEquals(120, result);
    }
}

使用 TestNG

import org.testng.Assert;
import org.testng.annotations.Test;

public class PriceCalculatorTest {

    @Test
    public void shouldAddPriceAndShipping() {
        PriceCalculator calculator = new PriceCalculator();

        int result = calculator.add(100, 20);

        Assert.assertEquals(result, 120);
    }
}

对普通单元测试而言,两者都很直观。不能因为 TestNG 的 @Test 可以设置更多属性,    就认为它一定更适合单元测试。单元测试最重要的是彼此独立、执行快速、结果稳定,很多高级执行功能实际上用不到。

三、参数化测试:两边都能做好,不必因此单独换框架

有一种常见说法是“需要数据驱动测试就应该使用 TestNG”。这个说法过去容易让人接受,    因为 TestNG 的 @DataProvider 很成熟,但现在如果只是普通参数化测试,JUnit 5 同样能够自然处理。

例如测试多组加法数据。

JUnit 5 参数化测试

import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.CsvSource;

import static org.junit.jupiter.api.Assertions.assertEquals;

class PriceCalculatorTest {

    private final PriceCalculator calculator = new PriceCalculator();

    @ParameterizedTest
    @CsvSource({
        "100, 20, 120",
        "50, 10, 60",
        "0, 15, 15"
    })
    void shouldAddPriceAndShipping(int price, int shipping, int expected) {
        assertEquals(expected, calculator.add(price, shipping));
    }
}

TestNG DataProvider

import org.testng.Assert;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;

public class PriceCalculatorTest {

    private final PriceCalculator calculator = new PriceCalculator();

    @DataProvider(name = "priceData")
    public Object[][] priceData() {
        return new Object[][] {
            {100, 20, 120},
            {50, 10, 60},
            {0, 15, 15}
        };
    }

    @Test(dataProvider = "priceData")
    public void shouldAddPriceAndShipping(
            int price,
            int shipping,
            int expected) {

        Assert.assertEquals(
            calculator.add(price, shipping),
            expected
        );
    }
}

如果数据就在代码附近,JUnit 5 的 @CsvSource、@ValueSource 等写法通常很紧凑;    如果测试数据需要由代码动态构造,TestNG 的 @DataProvider 也很自然。    JUnit 5 同样可以通过方法或自定义参数源提供复杂数据,因此“是否需要参数化测试”本身并不足以决定框架。

四、分组测试:JUnit 5用Tag,TestNG用Group

实际项目经常需要区分快速单元测试、数据库集成测试和耗时测试。例如 CI 中每次提交只运行快速测试,    夜间任务再运行完整测试集。

JUnit 5 可以使用 @Tag:

import org.junit.jupiter.api.Tag;
import org.junit.jupiter.api.Test;

class OrderServiceTest {

    @Test
    @Tag("fast")
    void calculateTotal() {
        // 快速测试
    }

    @Test
    @Tag("integration")
    void saveOrderToDatabase() {
        // 集成测试
    }
}

TestNG 则直接通过 groups 设置:

import org.testng.annotations.Test;

public class OrderServiceTest {

    @Test(groups = "fast")
    public void calculateTotal() {
        // 快速测试
    }

    @Test(groups = "integration")
    public void saveOrderToDatabase() {
        // 集成测试
    }
}

两种方法都能过滤测试。TestNG 的 group 与 Suite、依赖关系等执行配置结合得比较紧密;    JUnit 5 的 Tag 则与 JUnit Platform 的发现和过滤机制结合。

五、TestNG真正有特点的地方:测试依赖关系

TestNG 可以直接描述“测试 B 依赖测试 A”。例如某个接口自动化测试需要先创建用户,再查询这个用户:

import org.testng.annotations.Test;

public class UserApiTest {

    @Test
    public void createUser() {
        // 创建用户
    }

    @Test(dependsOnMethods = "createUser")
    public void queryUser() {
        // createUser 成功后再执行
    }
}

如果 createUser() 失败,依赖它的测试可以被跳过。TestNG 还支持基于 group 建立依赖。

这里需要注意:    能设置测试依赖,并不意味着普通单元测试就应该大量使用依赖。    单元测试通常应该可以单独运行。如果 A 测试失败就导致 B、C、D 全部无法执行,    定位问题反而会变困难。依赖机制更适合真正存在流程关系的集成测试或自动化测试。

JUnit 5 可以控制测试顺序,也能通过生命周期方法完成初始化,但它并没有把    dependsOnMethods 这种测试方法依赖关系作为核心测试模型。    这正是两者设计思路上的一个明显区别。

JUnit 5与TestNG对比:Java测试框架怎么选
图2:不要为了使用依赖功能而制造依赖;先判断测试本身是否真的存在业务流程关系。

六、并行测试:两者都支持,但配置思路不同

“TestNG 能并行、JUnit 只能串行”也是一个需要修正的说法。JUnit Jupiter 已经支持并行执行,    只是默认仍采用顺序执行,需要显式开启。TestNG 同样提供多种并行方式,并且 Suite 层面的配置比较直观。 

JUnit 5开启并行执行

可以在测试资源目录的 junit-platform.properties 中配置:

junit.jupiter.execution.parallel.enabled=true
junit.jupiter.execution.parallel.mode.default=concurrent

实际项目开启并行后,还需要检查测试是否共享静态变量、数据库记录、临时文件、端口或者其他外部资源。    测试框架允许并行,并不代表现有测试代码天然线程安全。

TestNG通过Suite控制并行方式

例如下面的 testng.xml 以测试类为并行单位:




    
        
            
            
        
    

TestNG 可以围绕 methods、classes、tests、instances 等不同粒度安排并行执行。    对测试平台或者自动化测试工程来说,这种显式的 Suite 编排方式很实用。

七、扩展能力:JUnit 5的Extension模型更值得关注

JUnit 5 提供统一的 Extension 扩展机制,可以在测试生命周期、参数解析、条件执行等位置接入自己的逻辑。    常见写法是通过 @ExtendWith 注册扩展。:contentReference[oaicite:2]{index=2}

这也是为什么在很多以单元测试和框架集成为主的 Java 项目中,JUnit 5 用起来比较自然。    测试框架、Mock 工具以及应用框架可以通过扩展机制参与测试生命周期,而业务测试本身仍保持比较简单。

TestNG 则拥有 Listener 等扩展接口,并且自身执行模型提供了很多可配置点。如果你建设的是一个测试平台,    希望大量控制执行前后事件、结果处理、重试以及 Suite 行为,同样有较大的扩展空间。

八、用Maven或Gradle时怎么配置

下面使用具体版本演示依赖写法。示例采用 JUnit 5.14.4 和 TestNG 7.12.0;    如果项目已经由 Spring Boot BOM、公司统一 BOM 或其他依赖管理机制控制版本,应优先遵守项目自己的依赖管理,    不要为了照搬示例强制覆盖版本。JUnit 5.14.4 于 2026 年发布,TestNG 官方仓库目前也已发布 7.12.0。

Maven使用JUnit 5


    org.junit.jupiter
    junit-jupiter
    5.14.4
    test

在项目根目录运行:

mvn test

Maven使用TestNG


    org.testng
    testng
    7.12.0
    test

同样执行:

mvn test

Gradle使用JUnit 5

dependencies {
    testImplementation("org.junit.jupiter:junit-jupiter:5.14.4")
}

test {
    useJUnitPlatform()
}

Gradle使用TestNG

dependencies {
    testImplementation("org.testng:testng:7.12.0")
}

test {
    useTestNG()
}
JUnit 5与TestNG对比:Java测试框架怎么选
图3:实际选择时,先看测试组织模式,再看某个功能是否存在。

九、几个常见项目应该怎么选

场景1:新建Spring Boot后端项目

主要需求是 Service、Controller、Repository 等常规测试,同时会使用 Mock、Spring Test 等工具。    这种项目通常直接使用 JUnit 5 更省事。

Spring Boot 的测试依赖体系本身对 JUnit Jupiter 有直接支持。如果项目由 Spring Boot 管理 JUnit 版本,    一般也没有必要另外导入 JUnit BOM 再覆盖一遍版本。

场景2:大量接口自动化测试

如果测试需要按照环境拆 Suite,需要执行 smoke、regression、production-check 等 group,    又存在登录、初始化数据、执行操作、清理环境等明显的流程关系,TestNG 会比较顺手。

场景3:大量参数组合测试

不要只因为“数据很多”就默认选择 TestNG。JUnit 5 的参数化测试已经能够处理多种参数来源。    如果项目其他部分更适合 JUnit 5,没有必要只为了 DataProvider 风格而更换框架。

场景4:需要高并发运行大量测试

两者都可以考虑。真正决定效果的通常不是框架名字,而是测试是否线程安全、外部环境能承受多少并发、    数据能否隔离以及 CI 机器有多少资源。

如果团队希望通过 Suite 明确控制 methods、classes、tests 等并行粒度,TestNG 的配置方式比较直接;    如果项目已经全面采用 JUnit Jupiter,也完全可以继续使用 JUnit 5 的并行执行能力。

场景5:旧项目已经有数千个TestNG测试

不建议仅仅因为新项目更常见 JUnit 5,就立即全部迁移。测试代码迁移不仅是修改 import,    还可能涉及生命周期方法、Listener、Group、DataProvider、Suite、执行顺序以及 CI 配置。

只有当现有 TestNG 方案已经明显影响维护,或者项目准备统一到 JUnit Platform 生态时,    才值得评估分阶段迁移。

十、JUnit 5和TestNG能不能同时存在

技术上可以,但“能同时使用”和“应该长期混用”是两个问题。

如果项目正在迁移,保留一部分 TestNG 测试,同时新增 JUnit 5 测试是可以理解的。    但如果没有明确原因,长期让开发人员在两个框架之间切换,会产生额外的认知成本:    生命周期注解不同、断言参数习惯可能不同、分组方式不同、执行配置也不同。

因此更合理的方式通常是确定一个主框架。另一个框架只在迁移阶段或确实存在特殊测试需求时使用。

十一、核心能力对比

比较项目JUnit 5TestNG
普通单元测试非常适合非常适合
参数化测试@ParameterizedTest及多种参数源@DataProvider
测试分类@Taggroups
方法之间建立依赖不是核心测试模型原生支持dependsOnMethods、dependsOnGroups
并行执行支持,需要配置执行模式支持,Suite级配置较直接
测试套件JUnit Platform提供套件与过滤机制testng.xml能力比较突出
扩展方式统一Extension模型Listener及其他扩展接口
嵌套组织测试@Nested表达能力很好通常按类、Group和Suite组织
复杂测试流程编排通常保持测试独立或借助外围工具Group、Dependency、Suite组合更直接
适合的新项目类型普通Java、Spring、Spring Boot单元/集成测试复杂自动化测试、流程测试、测试平台
JUnit 5与TestNG对比:Java测试框架怎么选
图4:JUnit 5 与 TestNG 的选择总结,框架应服从项目的测试组织方式。

十二、怎么做最终决定

如果现在面对的是一个没有历史包袱的新 Java 项目,可以先问自己三个问题。

  1. 测试是不是以相互独立的单元测试和常规集成测试为主?      如果是,JUnit 5 通常就是简单而稳妥的选择。

  2. 是否真的需要测试之间的依赖关系、复杂 Group、XML Suite 和多层执行编排?      如果这些能力会频繁出现,TestNG 的优势才会明显。

  3. 项目是不是已经形成了稳定的测试体系?      如果已有大量 JUnit 5 或 TestNG 测试,不要仅因为另一个框架某项功能更漂亮就整体迁移。

可以把结论简化成一句话:    新建的常规 Java 项目优先考虑 JUnit 5;需要明显的测试流程依赖、Group/Suite 编排和复杂执行控制时,再重点考虑 TestNG。

两个框架之间并不存在简单的“谁淘汰谁”。JUnit 5 已经具备参数化、标签过滤、扩展和并行测试等成熟能力;    TestNG 的价值也并不只是 DataProvider,而在于它把分组、依赖、Suite 和执行策略放在了测试模型的核心位置。    只要根据项目真正的测试组织方式选择,而不是根据单个注解或一张功能数量表决定,通常就不会选错。

文中涉及的 JUnit 5 并行执行、Tag、Extension、当前 5.x 版本以及 TestNG Group、DataProvider、    Dependency、并行执行和当前版本信息,依据 JUnit 与 TestNG 官方文档及官方发布记录核对。    

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系bd@zhengruan.com
作者最新文章
编程开发 Java测试
相关文章 更多
Java单元测试入门:使用JUnit 5编写第一个测试用例
Java单元测试入门:使用JUnit 5编写第一个测试用例

面向初学者的JUnit 5实用入门指南。从测试概念、Maven依赖配置,到手把手编写首个单元测试用例及断言验证,助你掌握Java单元测试的核心流程。

Java测试中怎么使用Mockito模拟依赖对象
Java测试中怎么使用Mockito模拟依赖对象

详细讲解在Java单元测试中如何使用Mockito模拟依赖对象,包括引入依赖、创建Mock、打桩返回值、行为验证以及Mock与Spy的核心差异和常见陷阱排查。

junit的基本用法教程及实例演示
junit的基本用法教程及实例演示

详解JUnit测试框架的基本用法,包括@Test注解、常用断言方法及测试生命周期,配合完整代码实例,帮助Java开发者高效编写和维护单元测试。

NUnit参数化测试教程:.NET微服务实战应用
NUnit参数化测试教程:.NET微服务实战应用

使用NUnit参数化测试可提升.NET微服务测试覆盖率。通过TestCase传递简单参数,TestCaseSource处理复杂数据,并结合依赖注入模拟服务上下文,实现高效、可维护的多场景验证,增强代码质量与系统健壮性。

Java JUnit 单元测试的完全指南
Java JUnit 单元测试的完全指南

简介JUnit是一个用于Java代码单元测试的开源框架,由ErichGamma和KentBeck创立于1997年。它允许开发者编写可验证代码正确性的测试用例。通过单元测试,开发者可以确保代码在单个单元级别按预期工作,从而提高代码的健壮性和可靠性。基本用法JUnit测试用例是一个以@Test注释的方法,该方法通常以test开头。它包含以下部分:设置:在@Before方法中,为每个测试用例设置必要的状态。测试:在@Test方法中,执行要测试的逻辑并验证结果。清理:在@After方法中,在每个测试用例后清理状态

编写简单易懂的Java测试类:提升代码可靠性方法
编写简单易懂的Java测试类:提升代码可靠性方法

简单易懂的Java测试类编写方法:让你的代码更可靠引言:在软件开发过程中,编写测试代码是一个非常重要的环节。通过测试代码,我们可以验证我们的代码是否能够正常运行,并且能够在后续的开发中快速定位和修复问题。本文将介绍一种简单易懂的Java测试类编写方法,帮助读者更好地进行代码测试。什么是测试代码?测试代码是一段用于验证程序功能的代码,其目的是判断代码是否按照预

Java测试的关键职责是什么?
Java测试的关键职责是什么?

探索Java测试的核心任务是什么?随着软件开发的快速发展,测试也成为了确保软件质量的关键环节之一。而在Java开发中,测试更是不可或缺的一部分。Java测试主要包括单元测试、集成测试以及系统测试等不同层次的测试环节。那么,Java测试的核心任务是什么呢?本文将对此进行探索。首先,Java测试的核心任务之一是保证代码的正确性。无论是单元测试还是集成测试,它们的

Java测试的主要任务是什么?
Java测试的主要任务是什么?

Java测试的主要工作是什么?在软件开发的整个生命周期中,测试是一个至关重要的环节。测试的目标是确保软件的质量,以及验证软件是否符合需求和预期。Java是一种广泛使用的编程语言,广泛应用于企业级应用、移动应用、云服务等领域。在Java开发中,测试也扮演着至关重要的角色。Java测试的主要工作包括以下几个方面:单元测试(UnitTesting):单元测试是测

Java测试的职责和职能主要有哪些?
Java测试的职责和职能主要有哪些?

了解Java测试的主要工作职能有哪些?摘要:随着软件开发技术的日益发展,测试工作在软件生命周期中变得越来越重要。在Java开发中,测试不仅仅是为了确保代码的质量,还为了确认软件是否满足需求和预期。本文将介绍Java测试的主要工作职能,包括测试计划制定、测试用例设计、测试执行和结果分析等。正文:测试计划制定测试计划是测试工作的基础,它描述了测试的范围、目标、资

使用 TestNG 进行单元测试的 Java API 开发
使用 TestNG 进行单元测试的 Java API 开发

JavaAPI是我们平常开发中经常使用的工具,而单元测试则是保证代码质量的重要手段之一。在这个过程中,TestNG(TestNextGeneration)框架可以帮助我们进行单元测试的自动化。在本文中,我将介绍如何在JavaAPI开发中使用TestNG进行单元测试。一、TestNG简介TestNG是一个基于Java开发的测试框架,旨

查看更多
精品专题 更多
装机必备
装机必备

正软商城装机必备专区,精选办公、浏览器、安全防护、影音播放、压缩解压、设计创作和系统工具等电脑常用正版软件,帮助用户快速完成新电脑软件配置。

Windows
Windows

正软商城Windows软件专区,汇集适用于Windows电脑的办公、设计、安全防护、影音播放、开发工具和系统优化软件,提供软件介绍、系统要求、正版授权及购买下载服务。

PDF教程
PDF教程

正软商城PDF教程频道提供PDF编辑、转换、合并、拆分、压缩及格式处理方法,同时介绍常用PDF软件和工具的使用技巧。

Mac软件 更多
AirBuddy 3 macOS版
AirBuddy 3 macOS版
macOS

AirBuddy 3 是面向 macOS 的蓝牙外设增强工具,可集中查看 AirPods、Beats 与苹果设备电量,提供快速连接、播放控制、电量提醒、桌面小组件和多台 Mac 外设接力等功能。

AirServer macOS版
AirServer macOS版
macOS

AirServer macOS版可把 Mac 转换为无线投屏接收端,通过 AirPlay 或 Google Cast 接收手机、平板和电脑画面,并支持多设备同时连接、高清镜像及会话录制,适合家庭娱乐、课堂教学、会议演示和应用展示。

AnyDesk macOS版
AnyDesk macOS版
macOS

AnyDesk macOS版是一款适用于远程办公、设备维护和客户支持的远程桌面工具,可连接并操作异地计算机,支持文件传输、无人值守访问、会话权限控制及跨平台协作。

WINDOWS 更多
讯飞绘文 网页版
讯飞绘文 网页版
Windows

讯飞绘文网页版是科大讯飞推出的AI图文创作与内容运营工具,覆盖热点选题、文章生成、稿件校对、智能配图、排版发布和数据复盘等环节,适合自媒体创作者及内容团队在线使用。

AirServer Windows版
AirServer Windows版
Windows

AirServer Windows版可把电脑变成AirPlay、Google Cast和Miracast无线投屏接收端,适合会议演示、课堂教学及家庭大屏分享。发送设备通常无需另装客户端,并可同时接收和智能排列多个镜像会话。

AlwaysUp Windows版
AlwaysUp Windows版
Windows

AlwaysUp是一款面向Windows的系统服务注册与程序托管工具,可让普通应用、脚本及批处理在无人登录时随系统启动,并通过状态检测、异常重启、资源监控和邮件通知保障关键任务持续运行。