How would you use these annotations in a practical test case?

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."