JUnit 5 Test Lifecycle

JUnit 5 lifecycle annotations control setup and teardown around tests and test classes. They let you run preparation and cleanup code at defined points before and after test methods or the entire test class.

JUnit 5 uses annotations such as `@BeforeEach` and `@AfterEach` to manage work around individual test methods. A method annotated with `@BeforeEach` runs before each test, while `@AfterEach` runs after each test, making them useful for resetting test state or releasing resources.

For class-level setup and cleanup, use `@BeforeAll` and `@AfterAll`. These methods run once for the test class rather than once per test method. By default, such methods are expected to be `static`, although JUnit can support non-static lifecycle methods when the test instance lifecycle is configured appropriately.

A typical lifecycle is: class-level setup, per-test setup, test method, per-test cleanup, and finally class-level cleanup. If several test methods exist, the per-test setup and cleanup stages repeat for every test.

Lifecycle methods should generally be small and focused on test infrastructure rather than business assertions. Keeping setup predictable helps tests remain isolated and makes failures easier to diagnose.

Key points

Interview questions

Why is test isolation important when using lifecycle methods?

A test suite is easier to trust when one test does not depend on state left by another. `@BeforeEach` can establish fresh state and `@AfterEach` can remove resources or mutations created by the test. Shared state initialized in `@BeforeAll` can be appropriate, but it increases the risk that one test changes what another test observes. Good lifecycle design therefore balances setup cost with independence and reproducibility.

Are JUnit 5 lifecycle methods guaranteed to run in a particular order?

JUnit defines the relationship between lifecycle stages, such as class-level setup occurring before test execution and per-test setup occurring before its test. When multiple lifecycle methods of the same annotation are present, developers should not generally rely on an arbitrary source-code order. If ordering is important, combine related setup into one method or use the documented ordering mechanisms. Tests should avoid depending on incidental execution order.

What is the purpose of `@BeforeEach` in JUnit 5?

`@BeforeEach` marks a method that JUnit runs before every test method in the class. It is commonly used to create fresh test data, initialize mocks, or reset state. Because it runs for each test, it helps keep tests independent. It should normally contain only the setup required by the tests.

What is the difference between `@BeforeAll` and `@BeforeEach`?

`@BeforeAll` runs once for the test class, whereas `@BeforeEach` runs before every test method. Class-level setup is appropriate for expensive resources that can safely be shared across tests. Per-test setup is better when each test needs fresh state. By default, `@BeforeAll` methods must be `static` unless the test instance lifecycle is configured to allow otherwise.

When should you use `@AfterEach`?

Use `@AfterEach` for cleanup that must happen after every test method. Typical examples include resetting mutable state, closing a resource created for the test, or clearing temporary test data. It is especially useful when cleanup must occur even if the test fails. Keeping this cleanup close to the test lifecycle reduces cross-test interference.