news 2026/5/30 0:14:49

JUnit4测试生命周期

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
JUnit4测试生命周期

JUnit4 测试生命周期详解

概述

理解JUnit4测试生命周期是编写有效单元测试的关键。本文件详细说明测试的执行流程、实例化策略、注解执行顺序等核心概念。

1. 测试生命周期总览

完整的测试执行流程图

┌─────────────────────────────────────────────────────┐
│ 测试类加载 │
├─────────────────────────────────────────────────────┤
│ @BeforeClass 方法执行 │
│ (整个类生命周期只执行一次) │
├─────────────────────────────────────────────────────┤
│ │
│ 对于每个@Test方法: │
│ ┌─────────────────────────────────────────────┐ │
│ │创建新的测试实例│ │
│ ├─────────────────────────────────────────────┤ │
│ │ @Before 方法执行 │ │
│ ├─────────────────────────────────────────────┤ │
│ │ @Test 方法执行 │ │
│ ├─────────────────────────────────────────────┤ │
│ │ 可能执行:@Test(expected) │ │
│ │ 可能执行:@Test(timeout) │ │
│ ├─────────────────────────────────────────────┤ │
│ │ @After 方法执行 │ │
│ │ (即使@Test抛出异常也会执行) │ │
│ └─────────────────────────────────────────────┘ │
│ │
├─────────────────────────────────────────────────────┤
│ @AfterClass 方法执行 │
│ (整个类生命周期只执行一次) │
└─────────────────────────────────────────────────────┘

2. 测试类实例化策略

2.1 默认行为:每个测试方法一个实例

JUnit4默认情况下为每个@Test方法创建新的测试实例

importorg.junit.Before;importorg.junit.Test;importstaticorg.junit.Assert.*;publicclassTestInstancePerMethodTest{privateintinstanceCounter=0;publicTestInstancePerMethodTest(){System.out.println("构造函数被调用,创建新实例");instanceCounter=0;// 每次创建新实例时重置}@BeforepublicvoidsetUp(){instanceCounter++;System.out.println("setUp() 执行,instanceCounter: "+instanceCounter);}@TestpublicvoidtestMethod1(){System.out.println("testMethod1 执行,instanceCounter: "+instanceCounter);// 这个实例的instanceCounter是1assertEquals(1,instanceCounter);}@TestpublicvoidtestMethod2(){System.out.println("testMethod2 执行,instanceCounter: "+instanceCounter);// 新的实例,所以instanceCounter也是1assertEquals(1,instanceCounter);}}/* 输出示例: 构造函数被调用,创建新实例 setUp() 执行,instanceCounter: 1 testMethod1 执行,instanceCounter: 1 构造函数被调用,创建新实例 setUp() 执行,instanceCounter: 1 testMethod2 执行,instanceCounter: 1 */

2.2 验证不同实例

publicclassDifferentInstancesTest{privateintinstanceId=(int)(Math.random()*1000);@TestpublicvoidtestInstance1(){System.out.println("testInstance1 - instanceId: "+instanceId);// 保存当前实例IDintcurrentId=instanceId;// 修改实例变量instanceId=999;// 验证修改只影响当前实例assertEquals(999,instanceId);// 在其他测试中这个修改不会生效}@TestpublicvoidtestInstance2(){System.out.println("testInstance2 - instanceId: "+instanceId);// 这是一个新的实例,所以instanceId是新的随机值// 不是999!assertNotEquals(999,instanceId);}}

2.3 为什么每个测试方法创建新实例?

设计目的

  1. 测试隔离:确保测试之间不会相互影响

  2. 线程安全:每个测试在独立的实例上运行

  3. 状态重置:避免测试间的状态污染

3. 注解执行顺序详解

3.1 完整的执行顺序

BeforeClass>{构造函数>Before>Test>After} * N>AfterClass

importorg.junit.*;publicclassFullLifecycleTest{// ===== 类级别生命周期 =====@BeforeClasspublicstaticvoidbeforeClass(){System.out.println("1. @BeforeClass - 类级别初始化");}@AfterClasspublicstaticvoidafterClass(){System.out.println("9. @AfterClass - 类级别清理");}// ===== 实例级别生命周期 =====@Beforepublicvoidbefore(){System.out.println(" 3. @Before - 测试方法前执行");}@Afterpublicvoidafter(){System.out.println(" 5. @After - 测试方法后执行");}// ===== 测试方法 =====@TestpublicvoidtestOne(){System.out.println(" 4. @Test testOne 执行");}@TestpublicvoidtestTwo(){System.out.println(" 4. @Test testTwo 执行");}// ===== 构造函数 =====publicFullLifecycleTest(){System.out.println("2. 构造函数 - 创建测试实例");}}/** * 1. @BeforeClass - 类级别初始化 * 2. 构造函数 - 创建测试实例 * 3. @Before - 测试方法前执行 * 4. @Test testOne 执行 * 5. @After - 测试方法后执行 * 2. 构造函数 - 创建测试实例 * 3. @Before - 测试方法前执行 * 4. @Test testTwo 执行 * 5. @After - 测试方法后执行 * 9. @AfterClass - 类级别清理 */

3.2 异常情况下的生命周期

场景1:@Before抛出异常

@Before异常了,@After还是会执行的,只不过@Test不会执行了

publicclassExceptionInBeforeTest{@BeforepublicvoidsetUp(){System.out.println("@Before 执行");thrownewRuntimeException("@Before 中发生异常");}@AfterpublicvoidtearDown(){System.out.println("@After 执行");}@TestpublicvoidtestMethod(){System.out.println("测试方法执行");fail("这个测试不应该执行");}}/* 输出: @Before 执行 @After 执行 结果:测试失败,@Test方法不会执行,但@After仍然执行 */
场景2:@Test抛出异常

即使@Test报错了,@After还是会执行的

publicclassExceptionInTestTest{@BeforepublicvoidsetUp(){System.out.println("@Before 执行");}@AfterpublicvoidtearDown(){System.out.println("@After 执行(即使@Test抛出异常)");}@Test(expected=RuntimeException.class)publicvoidtestWithExpectedException(){System.out.println("抛出期望的异常");thrownewRuntimeException("测试异常");}@TestpublicvoidtestWithUnexpectedException(){System.out.println("抛出未期望的异常");thrownewRuntimeException("意外异常");}}/* 第一个测试输出: @Before 执行 抛出期望的异常 @After 执行(即使@Test抛出异常) 结果:测试通过(因为异常符合expected) 第二个测试输出: @Before 执行 抛出未期望的异常 @After 执行(即使@Test抛出异常) 结果:测试失败(未期望的异常) */
场景3:@After抛出异常
publicclassExceptionInAfterTest{@TestpublicvoidtestSuccess(){System.out.println("测试成功执行");}@TestpublicvoidtestFailure(){System.out.println("测试失败执行");fail(<
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/5/22 17:23:43

iOS调试兼容性终极解决方案:全版本DeviceSupport文件使用指南

iOS调试兼容性终极解决方案&#xff1a;全版本DeviceSupport文件使用指南 【免费下载链接】iOSDeviceSupport All versions of iOS Device Support 项目地址: https://gitcode.com/gh_mirrors/ios/iOSDeviceSupport 调试困境&#xff1a;iOS开发者的共同痛点 作为iOS开…

作者头像 李华
网站建设 2026/5/30 12:23:46

vue基于Spring Boot的“健康”诊所药品仓库管理系统的应用和研究_529jlwi1

目录具体实现截图项目介绍论文大纲核心代码部分展示项目运行指导结论源码获取详细视频演示 &#xff1a;文章底部获取博主联系方式&#xff01;同行可合作具体实现截图 本系统&#xff08;程序源码数据库调试部署讲解&#xff09;同时还支持java、ThinkPHP、Node.js、Spring B…

作者头像 李华
网站建设 2026/5/30 10:57:43

AriaNg:重新定义下载管理的用户体验进化

你是否曾为复杂的命令行参数而头疼&#xff1f;是否在手机和电脑之间切换时感到下载管理的不便&#xff1f;今天&#xff0c;让我们一起探索AriaNg下载管理如何通过Web应用技术实现技术普及化&#xff0c;让专业级下载能力触手可及。 【免费下载链接】AriaNg AriaNg, a modern …

作者头像 李华
网站建设 2026/5/30 11:28:09

如何快速提升设计效率:终极标注工具完全指南

如何快速提升设计效率&#xff1a;终极标注工具完全指南 【免费下载链接】sketch-meaxure 项目地址: https://gitcode.com/gh_mirrors/sk/sketch-meaxure 在当今快节奏的设计工作中&#xff0c;设计效率和团队协作是每个设计师都必须面对的核心挑战。从设计稿的创建到最…

作者头像 李华