1. 概述
本文将深入解析JUnit 4和5中@Before
、@BeforeClass
、@BeforeEach
和@BeforeAll
注解的核心区别,并通过实际示例演示它们的使用场景。同时也会简要介绍其对应的@After
系列注解。
2. @Before
✅ 核心特点:@Before
注解的方法会在每个测试方法执行前运行。当需要为每个测试执行通用初始化代码时特别实用。
以下示例展示了如何初始化一个列表并添加初始值:
@RunWith(JUnit4.class)
public class BeforeAndAfterAnnotationsUnitTest {
// ...
private List<String> list;
@Before
public void init() {
LOG.info("startup");
list = new ArrayList<>(Arrays.asList("test1", "test2"));
}
@After
public void teardown() {
LOG.info("teardown");
list.clear();
}
}
⚠️ 注意:我们同时添加了@After
注解的清理方法,确保每个测试后重置环境。
现在添加两个测试方法验证列表大小:
@Test
public void whenCheckingListSize_thenSizeEqualsToInit() {
LOG.info("executing test");
assertEquals(2, list.size());
list.add("another test");
}
@Test
public void whenCheckingListSizeAgain_thenSizeEqualsToInit() {
LOG.info("executing another test");
assertEquals(2, list.size());
list.add("yet another test");
}
关键点:每个测试执行前必须重置环境,因为测试过程中会修改列表内容。查看日志输出可确认init
和teardown
在每个测试前后各执行一次:
... startup
... executing another test
... teardown
... startup
... executing test
... teardown
3. @BeforeClass
✅ 核心特点:当需要在所有测试执行前执行一次昂贵的通用操作时,@BeforeClass
是最佳选择。典型场景包括创建数据库连接或启动服务器。
以下示例模拟数据库连接的创建:
@RunWith(JUnit4.class)
public class BeforeClassAndAfterClassAnnotationsUnitTest {
// ...
@BeforeClass
public static void setup() {
LOG.info("startup - creating DB connection");
}
@AfterClass
public static void tearDown() {
LOG.info("closing DB connection");
}
}
⚠️ 注意:这些方法必须是静态的,因为它们在类实例化前执行。
添加简单测试验证:
@Test
public void simpleTest() {
LOG.info("simple test");
}
@Test
public void anotherSimpleTest() {
LOG.info("another simple test");
}
日志显示setup
和tearDown
在整个测试类生命周期中仅执行一次:
... startup - creating DB connection
... simple test
... another simple test
... closing DB connection
4. @BeforeEach 和 @BeforeAll
✅ 核心关系:@BeforeEach
和@BeforeAll
是JUnit 5中@Before
和@BeforeClass
的等价注解。新命名更清晰地表达了执行时机。
4.1 @BeforeEach 示例
class BeforeEachAndAfterEachAnnotationsUnitTest {
// ...
private List<String> list;
@BeforeEach
void init() {
LOG.info("startup");
list = new ArrayList<>(Arrays.asList("test1", "test2"));
}
@AfterEach
void teardown() {
LOG.info("teardown");
list.clear();
}
// ...
}
日志输出与JUnit 4的@Before
/@After
完全一致:
... startup
... executing another test
... teardown
... startup
... executing test
... teardown
4.2 @BeforeAll 示例
class BeforeAllAndAfterAllAnnotationsUnitTest {
// ...
@BeforeAll
static void setup() {
LOG.info("startup - creating DB connection");
}
@AfterAll
static void tearDown() {
LOG.info("closing DB connection");
}
// ...
}
输出与JUnit 4的@BeforeClass
/@AfterClass
相同:
... startup - creating DB connection
... simple test
... another simple test
... closing DB connection
5. 总结
注解 | 执行时机 | JUnit版本 | 典型场景 |
---|---|---|---|
@Before |
每个测试前 | 4 | 测试级别初始化 |
@BeforeClass |
所有测试前(仅一次) | 4 | 昂贵资源准备 |
@BeforeEach |
每个测试前 | 5 | 测试级别初始化 |
@BeforeAll |
所有测试前(仅一次) | 5 | 昂贵资源准备 |
选择建议:
- 需要频繁重置的轻量级初始化 →
@BeforeEach
(JUnit 5)或@Before
(JUnit 4) - 高成本的一次性准备操作 →
@BeforeAll
(JUnit 5)或@BeforeClass
(JUnit 4)
完整示例代码可在GitHub仓库获取。