@Before 与 @BeforeClass 与 @BeforeEach 与 @BeforeAll
上次更新:2024 年 1 月 8 日
1. 概述
在本简短教程中,我们将解释 JUnit 4 和 5 中 @Before、@BeforeClass、@BeforeEach 和 @BeforeAll 注解之间的区别——并提供如何使用它们的实际示例。
我们还将简要介绍它们的互补注解 @After。
让我们从 JUnit 4 开始。
更多阅读
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 的等效项。 这些注解被重新命名为更清晰的名称,以避免混淆。
让我们使用这些新的注解复制我们之前的类,从 @BeforeEach 和 @AfterEach 注解开始
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();
}
// ...
}
如果检查日志,我们可以确认它与 @Before 和 @After 注解的工作方式相同
... startup
... executing another test
... teardown
... startup
... executing test
... teardown
最后,让我们对另一个测试类执行相同的操作,以查看 @BeforeAll 和 @AfterAll 注解的作用
class BeforeAllAndAfterAllAnnotationsUnitTest {
// ...
@BeforeAll
static void setup() {
LOG.info("startup - creating DB connection");
}
@AfterAll
static void tearDown() {
LOG.info("closing DB connection");
}
// ...
}
输出与旧注解相同
... startup - creating DB connection
... simple test
... another simple test
... closing DB connection
5. 结论
在本文中,我们展示了 JUnit 中 @Before、@BeforeClass、@BeforeEach 和 @BeforeAll 注解之间的区别,以及应该在何时使用它们。
支持本文的代码可在 GitHub 上获取。 一旦你以 Baeldung Pro 会员 身份登录,就开始学习并在项目上进行编码。















