ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

用 Arrange/Act/Assert 组织单元测试:java-design-patterns 中 Cash 示例的 AAA 测试模式实战指南

用 Arrange/Act/Assert 组织单元测试:java-design-patterns 中 Cash 示例的 AAA 测试模式实战指南 示例工程教程【免费下载链接】java-design-patternsDesign patterns implemented in Java项目地址https://gitcode.com/GitHub_Trending/ja/java-design-patterns点击查看免费下载本文以 java-design-patterns 仓库中的 arrange-act-assert 模块为依托系统讲解 Arrange/Act/AssertAAA单元测试组织模式它如何把每个测试拆解为 Arrange准备、Act执行、Assert验证三个清晰步骤以及这套结构为什么能显著提升测试的可读性、可维护性与可调试性。读完本文你将掌握 AAA 模式的写法规范、适用边界并能对照本仓库源码Cash类与其正反两套测试在自己的 JUnit 测试中落地这一模式。模式概述Arrange/Act/Assert简称 AAA也被称为 Given/When/Then是一种用于组织单元测试的经典模式。它的核心思想是把每个单元测试拆分成三个明确且彼此分离的步骤Arrange准备完成测试所需的初始化与前置条件设置。Act执行执行被测代码的关键动作。Assert验证校验测试的预期结果。用更通俗的话说AAA 是一种把测试组织成三个清晰步骤、以便于维护的测试模式。WikiWikiWeb 将其概括为在 UnitTest 方法中组织和格式化代码的一种模式。为什么 AAA 值得坚持该模式带来两个显著的收益清晰的职责分离它在测试的准备工作、操作过程、结果断言之间建立了明确的边界。按顺序排布步骤并在代码中用空行或注释加以分隔后读者可以快速扫读测试瞬间理解它在测什么、怎么测、期望什么。写作纪律的养成它要求你在下笔前先想清楚测试将要经历的三个阶段。由于大纲已经存在测试写起来反而更自然同时保持着统一、可预测的结构。从本仓库源码的注释可以看到同样的表述见 CashAAATest.java每个测试方法应当只有一个变更理由、一个失败理由。在庞大而复杂的代码库中遵循单一职责原则的测试远比一个大方法测完一切的测试更容易排查问题。一个日常生活的类比假设你要组织一场小型活动。为了保证一切顺利你会遵循一个类似 AAA 的流程Arrange布置场地、准备宾客名单、安排座位、组织餐饮。Act按计划开展活动——迎宾、上菜、按日程推进。Assert活动结束后通过宾客反馈、任务完成情况来评估活动是否成功。这种准备—执行—评估的清晰切分正是 AAA 模式在软件测试中的写照。实战示例被测试的 Cash 类在 arrange-act-assert 模块中被测对象是一个简单的Cash类它封装了一个整数金额支持加、减与查询三个操作。以下是仓库中 Cash.java 的完整实现AllArgsConstructor public class Cash { private int amount; // plus向金额加上加数 void plus(int addend) { amount addend; } // minus若余额足够则扣减并返回 true否则返回 false boolean minus(int subtrahend) { if (amount subtrahend) { amount - subtrahend; return true; } else { return false; } } // count返回当前金额 int count() { return amount; } }值得注意的实现细节Cash用 Lombok 的AllArgsConstructor生成了全参构造器三个方法均为包级可见package-private测试类与主类同处com.iluwatar.arrangeactassert包下因此无需public即可访问。类图参见 arrange-act-assert.urm.pumlCash持有私有字段amount : int对外暴露plus、minus、count三个包级方法。minus的行为需要特别留意——它是一个带分支返回值的操作余额充足时扣减并返回true余额不足时不做扣减并返回false。这为后面设计失败路径测试提供了天然素材。按 AAA 编写的完整测试套件下面依据 AAA 模式编写Cash的单元测试。请仔细观察每个测试中三阶段的清晰分离完整源码见 CashAAATest.javaclass CashAAATest { Test void testPlus() { // Arrange var cash new Cash(3); // Act cash.plus(4); // Assert assertEquals(7, cash.count()); } Test void testMinus() { // Arrange var cash new Cash(8); // Act var result cash.minus(5); // Assert assertTrue(result); assertEquals(3, cash.count()); } Test void testInsufficientMinus() { // Arrange var cash new Cash(1); // Act var result cash.minus(6); // Assert assertFalse(result); assertEquals(1, cash.count()); } Test void testUpdate() { // Arrange var cash new Cash(5); // Act cash.plus(6); var result cash.minus(3); // Assert assertTrue(result); assertEquals(8, cash.count()); } }四个测试方法分别覆盖四条核心路径测试方法ArrangeActAssert 要点testPlus创建Cash(3)plus(4)金额变为 7testMinus创建Cash(8)minus(5)返回true金额变为 3testInsufficientMinus创建Cash(1)minus(6)返回false金额保持 1失败路径testUpdate创建Cash(5)plus(6)后再minus(3)返回true金额变为 8该模块在 pom.xml 中声明了junit-jupiter-engineJUnit 5测试作用域依赖断言使用assertEquals、assertTrue、assertFalse静态导入测试代码直接可运行。若在仓库根目录执行 Maven 测试可运行./mvnw test -pl arrange-act-assert反例警示没有 AAA 的测试长什么样为了说明 AAA 的价值仓库特意提供了一个反例——CashAntiAAATest.java。该测试功能上是正确的但把所有步骤揉进了一个 11 行的方法里Test void testCash() { // initialize var cash new Cash(3); // test plus cash.plus(4); assertEquals(7, cash.count()); // test minus cash new Cash(8); assertTrue(cash.minus(5)); assertEquals(3, cash.count()); assertFalse(cash.minus(6)); assertEquals(3, cash.count()); // test update cash.plus(5); assertTrue(cash.minus(5)); assertEquals(3, cash.count()); }这段代码的问题源码注释同样指出了这一点一个测试方法承载了过多步骤违反了单一职责原则它同时验证了 plus、minus、失败路径与复合操作一旦小幅改动后测试失败排查者需要花不少时间才能定位是哪一步、哪个行为出了问题中间还混入了对cash变量的重新赋值阅读时需要时刻跟踪状态变化。对比之下CashAAATest中每个测试方法都只有一个变更理由、一个失败理由——这正是 AAA 带来的可维护性红利。AAA 的完整流程Arrange/Act/Assert 测试模式流程图上图展示了 AAA 的完整执行流程以Start Test为起点依次经过Arrange设置测试数据与环境、Act执行待测操作、Assert验证结果三个阶段最终以Test Complete结束。三个阶段严格按序执行这正是模式名称所承诺的结构化流程。何时使用 AAA当你的目标是让单元测试更易读、易维护、易演进时就应该采用 Arrange/Act/Assert 模式。具体来说它尤其适用于单元测试特别是TDD测试驱动开发与 BDD行为驱动开发语境下的测试编写——TDD 的红-绿-重构循环天然需要可读、可定位的断言而 BDD 的 Given/When/Then 正是 AAA 的另一种表述任何需要测试用例具备清晰结构与可读性的场合。真实世界中的应用该模式在 Java 的 TDD/BDD 实践中被广泛采用它跨越多种语言与测试框架JUnitJava、NUnit.NET以及各类 xUnit 框架中都能看到 AAA 的踪迹。收益与权衡收益通过明确分离准备、执行与验证步骤显著提升测试的可读性每个测试按可预测的方式组织更易于维护和理解便于调试——测试失败可以被快速定位到具体阶段是准备数据错了、执行逻辑错了还是断言写错了。权衡可能引入一定的冗余——相似的 Arrange 准备代码会在多个测试间重复例如每个测试都new Cash(...)可通过提取BeforeEach公共初始化或工厂方法缓解少数复杂测试难以被整齐地装入这三段式结构需要额外的上下文或跨阶段的设置。相关模式与延伸阅读与Page Object模式天然互补Page Object 用于组织 UI 测试中的页面交互见仓库 page-object 模块其把页面操作封装成可复用方法的做法可与 AAA 结合让 UI 测试同样获得三阶段的清晰结构。参考来源本模式的概念梳理参考了以下公开资料NCrunch 博客的 Arrange, Act, Assert: What is AAA Testing?、Bill Wake 的 3A – Arrange, Act, Assert、Martin Fowler 关于 Given/When/Then 的阐述以及《xUnit Test Patterns: Refactoring Test Code》《Test Driven Development: By Example》《Unit Testing Principles, Practices, and Patterns》等测试专著。关于模式在本仓库中的一手实现与正反示例可直接阅读 Cash.java、CashAAATest.java 与 CashAntiAAATest.java。赞分享示例工程教程【免费下载链接】java-design-patternsDesign patterns implemented in Java项目地址https://gitcode.com/GitHub_Trending/ja/java-design-patterns点击查看免费下载相关推荐java-design-patterns 项目中的 Arrange/Act/AssertAAA测试模式以 Java 单元测试结构化提升可读性与可维护性java design patterns 项目中的 Arrange/Act/AssertAAA测试模式以 Java 单元测试结构化提升可读性与可维护性 A示例工程教程5分钟快速备份如何用开源工具一键提取24平台个人数据5分钟快速备份如何用开源工具一键提取24平台个人数据 你是否曾想过自己分散在各个网络平台的数据到底有多少从B站观看历史到淘宝购物记录从知乎回答到Git网页爬虫数据分析数据可视化桌面应用Quick 测试框架实战用 Arrange、Act、Assert 模式写出高效稳定的 Swift 单元测试Quick 测试框架实战用 Arrange、Act、Assert 模式写出高效稳定的 Swift 单元测试 无论你使用的是 XCTest、Quick 还是其他测试开发工具上一篇如何快速完成显卡显存检测memtest_vulkan 完整使用指南下一篇显卡硬件检测实战6分钟完成GPU显存测试揪出隐性硬件故障创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表