In JUnit 5, describe when the methods annotated @BeforeAll, @BeforeEach, @AfterEach and @AfterAll run relative to the test methods of a class, and what each is typically used for.
answer
- BeforeAll once → (BeforeEach, test, AfterEach) × N → AfterAll once
- mutable ⇒ @BeforeEach
- expensive + immutable ⇒ @BeforeAll
- teardown runs even after failure
- JUnit 4 names: BeforeClass/Before/After/AfterClass
basics
~20 s@BeforeAll runs once before any test in the class; @AfterAll runs once after the last one. @BeforeEach runs before every individual test and @AfterEach after every one, so for three tests you get one BeforeAll, three BeforeEach/test/AfterEach cycles, then one AfterAll.
solid answer
~40 sFor a class with N test methods the order is: 1. `@BeforeAll` — once, before any test. 2. For each test: `@BeforeEach` → the `@Test` method → `@AfterEach`. 3. `@AfterAll` — once, after the last test. So three tests give one `@BeforeAll`, three `@BeforeEach`/test/`@AfterEach` cycles and one `@AfterAll`. Use them by cost and scope. `@BeforeAll`/`@AfterAll` are for expensive, shared, ideally immutable setup — starting a container or an embedded server, loading a large fixture — and releasing it. `@BeforeEach`/`@AfterEach` are for per-test state: constructing the object under test, seeding and truncating data, resetting mocks, closing resources the test opened. The important habit is that per-test setup belongs in `@BeforeEach`, not `@BeforeAll`, because anything shared and mutable makes tests order-dependent.
code
java · 31 linesimport org.junit.jupiter.api.*;
class OrderServiceTest {
static Database db;
OrderService service;
@BeforeAll
static void startDatabase() { // once
db = Database.startEmbedded();
}
@BeforeEach
void freshService() { // before every test
db.truncateAll();
service = new OrderService(db);
}
@AfterEach
void closeService() { // after every test
service.close();
}
@AfterAll
static void stopDatabase() { // once
db.stop();
}
@Test void placesOrder() { /* ... */ }
@Test void rejectsEmptyOrder() { /* ... */ }
}go deeper
Recite the sequence accurately and give one concrete example of what goes in each hook.
Add the cost-versus-mutability rule for choosing between the per-class and per-test hooks, and note teardown still runs after a failure.
Talk about order independence as the property being protected, when sharing expensive fixtures is justified, and how hooks interact with parallel execution.
Frame it as suite architecture: per-test isolation as the default contract, shared fixtures as an explicit, documented exception with immutability as the price of admission.
## The four annotations JUnit Jupiter (JUnit 5) defines four lifecycle annotations in `org.junit.jupiter.api`: - `@BeforeAll` — executed once for the test class, before any test method runs. - `@BeforeEach` — executed before **every** test method. - `@AfterEach` — executed after **every** test method. - `@AfterAll` — executed once for the test class, after all test methods have finished. They replace JUnit 4's `@BeforeClass`, `@Before`, `@After` and `@AfterClass` respectively. Methods must not be `private`, and must return `void`. ## The exact sequence For a class with tests `t1`, `t2`, `t3`: ``` @BeforeAll @BeforeEach → t1 → @AfterEach @BeforeEach → t2 → @AfterEach @BeforeEach → t3 → @AfterEach @AfterAll ``` Note what this implies about instance state. Under the default per-method test-instance behaviour a new test-class instance is created for each test, so fields assigned in `@BeforeEach` are re-initialised every time and nothing you store in an instance field can leak between tests. That is the property the whole design is protecting. ## What belongs where **`@BeforeEach`.** Anything the test needs freshly built: instantiating the class under test, wiring in test doubles, resetting a database to a known state, creating a temp fixture. The rule of thumb is that if a test could mutate it, it must be created per test. **`@AfterEach`.** Undo what a test could have changed outside its own object graph: close resources, truncate tables, stop a server the test started, restore a system property or a static registry, delete files. Also useful for on-failure diagnostics — dumping state before it disappears. **`@BeforeAll`.** Expensive setup shared by all tests: starting a Testcontainers instance, booting an embedded broker, loading a large read-only fixture, computing a costly derived value. It should ideally produce something immutable. **`@AfterAll`.** Releasing exactly what `@BeforeAll` acquired — stopping the container, closing the connection pool, shutting down the executor. ## Why the split matters Moving setup from `@BeforeEach` to `@BeforeAll` is the classic "optimisation" that quietly breaks a suite. Once two tests share mutable state, results depend on execution order: the suite passes in the IDE, fails in CI where order differs, or fails only when a single test is run in isolation because it depended on a predecessor. Debugging that is far more expensive than the milliseconds saved. Share only what is genuinely costly and genuinely read-only. The symmetric mistake is putting expensive setup in `@BeforeEach` — starting a Docker container per test turns a two-minute suite into twenty. The judgement is cost versus mutability, and it is exactly what an interviewer is probing. ## Related guarantees - Teardown hooks are executed even when the test or an earlier setup hook fails, so cleanup is reliable. - Multiple methods carrying the same annotation in the same class are all executed, but their relative order is deterministic-yet-unspecified; never write two `@BeforeEach` methods that depend on each other's ordering — merge them or call one from the other. - Hooks may accept resolved parameters (for example a `TestInfo`, or a `@TempDir Path`), which is how JUnit passes contextual information into setup. - `@BeforeAll`/`@AfterAll` must be `static` under the default per-method instance behaviour, because there is no single instance to invoke them on. ## How to answer Give the sequence crisply, then immediately say what belongs in each and why — the ordering is trivia, but "expensive-and-immutable goes in `@BeforeAll`, anything mutable goes in `@BeforeEach`" is the reasoning that shows you have maintained a real suite. Adding that teardown still runs after a failed setup, and that `@BeforeAll` must be static by default, rounds it out.
- Two tests in a class both mutate an object created in @BeforeAll and one of them fails only when the full class runs. What is the fix?The shared mutable object makes the tests order-dependent: one test leaves state the other observes. Move its creation into @BeforeEach so each test gets a fresh instance, or, if construction is genuinely expensive, keep the costly part in @BeforeAll but derive a per-test copy in @BeforeEach. Never rely on execution order to make the pair pass.
- What are the JUnit 4 equivalents of these four annotations?@BeforeAll corresponds to @BeforeClass, @BeforeEach to @Before, @AfterEach to @After and @AfterAll to @AfterClass. The semantics are the same; JUnit 5 renamed them for clarity and added parameter resolution to the hooks. The static requirement for the class-level hooks carried over from JUnit 4, except that Jupiter can lift it with a per-class test-instance setting.
saying these in an interview costs you the question
- Saying @BeforeAll runs before each test rather than once per class
- Putting per-test mutable setup in @BeforeAll to 'speed things up'
- Believing @AfterEach is skipped when the test fails
- Assuming multiple @BeforeEach methods in one class run in declaration order
- Thinking @AfterAll runs after every test method