Test Overview
This test demonstrates how JUnit lifecycle hooks @BeforeEach and @AfterEach manage setup and teardown for each test method. It verifies that setup runs before and teardown runs after the test.
This test demonstrates how JUnit lifecycle hooks @BeforeEach and @AfterEach manage setup and teardown for each test method. It verifies that setup runs before and teardown runs after the test.
import org.junit.jupiter.api.*; import static org.junit.jupiter.api.Assertions.*; public class LifecycleHooksTest { private StringBuilder resource; @BeforeEach void setUp() { resource = new StringBuilder("start"); } @AfterEach void tearDown() { resource = null; } @Test void testModifyResource() { resource.append("-modified"); assertEquals("start-modified", resource.toString()); } @Test void testResourceIsFresh() { assertEquals("start", resource.toString()); } }
| Step | Action | System State | Assertion | Result |
|---|---|---|---|---|
| 1 | Test runner starts and prepares to run testModifyResource | No resource initialized yet | — | PASS |
| 2 | @BeforeEach setUp() runs, initializing resource with 'start' | resource = 'start' | — | PASS |
| 3 | testModifyResource() runs, appending '-modified' to resource | resource = 'start-modified' | assertEquals("start-modified", resource.toString()) | PASS |
| 4 | @AfterEach tearDown() runs, setting resource to null | resource = null | — | PASS |
| 5 | Test runner prepares to run testResourceIsFresh | resource is null from previous teardown | — | PASS |
| 6 | @BeforeEach setUp() runs again, initializing resource with 'start' | resource = 'start' | — | PASS |
| 7 | testResourceIsFresh() runs, checking resource value | resource = 'start' | assertEquals("start", resource.toString()) | PASS |
| 8 | @AfterEach tearDown() runs, setting resource to null | resource = null | — | PASS |
@BeforeEach and @AfterEach in JUnit tests?@BeforeEach and @AfterEach run code before and after each test method to prepare and clean up the test environment.@BeforeAll annotation runs a method once before any tests in the class run.@BeforeAll must be static in JUnit 5, so public static void init() is correct.class SampleTest {
static int counter = 0;
@BeforeEach
void beforeEach() {
counter++;
}
@Test
void testOne() {}
@Test
void testTwo() {}
@AfterAll
static void afterAll() {
System.out.println(counter);
}
}@AfterAll method must be static, which it is. However, counter is static and incremented in @BeforeEach which is non-static, so no issue there.@BeforeEach and @AfterEach methods to be non-static, which is correct here. But @AfterAll is static, so no problem.@TestInstance(Lifecycle.PER_CLASS) annotation if we want to use static fields properly with lifecycle hooks. Without it, static fields are fine but the test runner may not allow static @AfterAll without this annotation in some setups.2 is printed.class TestExample {
@BeforeAll
void setup() {
System.out.println("Setup");
}
@Test
void test() {
System.out.println("Test running");
}
}@BeforeAll must be static unless the test class is annotated with @TestInstance(Lifecycle.PER_CLASS).setup() method is not static, and the class lacks @TestInstance, so this causes a runtime error.@BeforeAll and @AfterAll run once per test class, ideal for this purpose. They must be static methods unless using @TestInstance(Lifecycle.PER_CLASS).Pass the test and this pattern moves unknown