JUnit 5easy0-2 years

In one JUnit 5 test class, `rejectsDuplicateEmail` passes when run on its own and fails when the whole class runs. The class keeps a `static List<Customer> saved` for its in-memory repository, and last week someone added `@TestInstance(Lifecycle.PER_CLASS)` so a `@BeforeAll` method could stop being static. Explain the Jupiter lifecycle rule these two changes work against, and how you would fix the class.

By default Jupiter creates a new instance of the test class for every test method. Instance fields are therefore fresh for each test, so state cannot leak between them, and @BeforeAll has to be static because it runs before any instance exists. Both changes defeat that. A static field belongs to the class, not the instance, so rows saved by one test are still there for the next. PER_CLASS goes further: one instance for the whole class, so even ordinary fields now survive from test to test. The test passes alone because it starts with an empty list and fails in the class because an earlier test left a customer behind. The fix is to make the state per test again: an instance field created in @BeforeEach, and the default lifecycle.

The lesson behind it →