@beforeeach和@aftereach在junit5中各执行一次于每个@test方法前后,作用于独立测试实例,无需static,用于初始化与清理;而@beforeall/@afterall在整个测试类生命周期中仅执行一次且必须为static。

@BeforeEach 和 @AfterEach 是 JUnit5 中控制单个测试方法粒度生命周期的核心注解,它们让测试环境的初始化与清理变得可预测、可复用、不污染。
作用范围明确:每个测试方法前后各执行一次
这两个注解标记的方法,会在每一个 @Test 方法执行前或执行后被调用,且每次都是针对一个独立的测试实例。JUnit5 默认为每个测试方法创建一个新的测试类实例,因此 @BeforeEach 和 @AfterEach 方法无需声明为 static,可以自由访问实例变量。
- @BeforeEach 方法适合做:创建新对象、打开临时文件、清空内存缓存、重置 mock 行为、开启数据库事务等
- @AfterEach 方法适合做:关闭资源(如流、连接)、回滚事务、删除临时文件、重置静态状态(需谨慎)、断言副作用是否清除等
典型使用场景示例
比如测试一个依赖数据库的服务:
Java JDK 25 来自 OpenJDK 官方归档,版本为 JDK 25,本条下载地址已指向官方 Windows x64 zip 安装包直链,适合调试旧项目或兼容旧版 Java 运行环境。
public class OrderServiceTest {
private OrderService orderService;
private DataSource dataSource;
@BeforeEach
void setUp() {
dataSource = TestDataSource.create(); // 创建轻量级测试数据源
orderService = new OrderService(dataSource);
DatabaseUtils.clearTables(dataSource, "orders"); // 清空表,确保干净起点
}
@Test
void shouldCreateOrderSuccessfully() {
Order order = orderService.create(new Order("user-123"));
assertNotNull(order.getId());
}
@Test
void shouldFailOnInvalidUser() {
assertThrows(IllegalArgumentException.class, () ->
orderService.create(new Order(null))
);
}
@AfterEach
void tearDown() {
DatabaseUtils.close(dataSource); // 确保每次测试后释放连接
}
}
这样,两个测试互不影响,哪怕其中一个失败,另一个仍能基于干净环境运行。
注意与 @BeforeAll / @AfterAll 的区别
@BeforeEach/@AfterEach 是“每测一次,执行一次”;而 @BeforeAll/@AfterAll 是“整个类所有测试加起来,只执行一次”,且必须是 static 方法。若误把数据库连接池初始化写在 @BeforeEach 里,会导致频繁创建销毁,拖慢测试;若误把清理逻辑写在 @AfterAll,可能因上一个测试异常中断,导致后续测试无法清理干净。
- 需要共享昂贵资源(如启动嵌入式 Redis)→ 放 @BeforeAll
- 需要隔离状态(如用户上下文、Mockito mock 实例)→ 放 @BeforeEach
- 需要逐个还原(如 ThreadLocal、静态计数器)→ 放 @AfterEach
常见陷阱提醒
实际项目中容易忽略几点:
- 如果 @BeforeEach 抛出异常,对应测试会直接标为失败,且 @AfterEach 不再执行 → 清理逻辑不能只依赖 @AfterEach,关键资源建议用 try-with-resources 或 finally 块兜底
- @AfterEach 即使测试失败也会执行,这是它比普通 finally 更可靠的地方
- 不要在 @BeforeEach 中做耗时操作(如读大文件、调外部服务),否则会显著拉长整体测试时间
- 多个 @BeforeEach 方法存在时,执行顺序不确定 → 避免拆分强依赖的初始化步骤
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










