JUnit lifecycle annotations control setup and teardown around tests, letting you prepare shared resources once and reset per-test state cleanly between runs.
Key Points: • @BeforeAll (static, runs once) sets up expensive shared resources like a database connection or embedded server. • @BeforeEach runs before every test method, resetting or preparing fresh data for that specific test. • @AfterEach cleans up per-test resources, such as closing streams or clearing inserted rows. • @AfterAll tears down the shared resource once, after all tests in the class finish. • Keeping tests independent this way prevents state from one test leaking into and breaking another.
Example: A repository test class opens a Testcontainers PostgreSQL instance once in @BeforeAll, inserts fresh seed data in @BeforeEach for each test, and truncates the tables in @AfterEach so every test starts from a known state.
Code Example:
class UserRepositoryTest {
@BeforeAll
static void startDb() { /* start container */ }
@BeforeEach
void seedData() { /* insert test rows */ }
@AfterEach
void cleanUp() { /* truncate tables */ }
@AfterAll
static void stopDb() { /* stop container */ }
}Interview Tip: A concise interview answer is:
"I use @BeforeAll for one-time expensive setup like starting a test database, @BeforeEach to prepare fresh data before each individual test, and @AfterEach or @AfterAll to clean up so no state leaks between tests. That keeps every test independent and repeatable regardless of run order."