In JUnit 5, when should you initialize test state in a @BeforeEach method versus in the test class's constructor or field initializers?
answer
- PER_METHOD: constructor + field init also run per test
- Order: constructor → extension BeforeEach → @BeforeEach → test
- Mocks/Spring beans injected after constructor → use @BeforeEach
- PER_CLASS: constructor runs once → per-test setup needs @BeforeEach
- No destructor in Java → teardown only in @AfterEach
basics
~20 sBecause JUnit makes a new test-class instance for each test, the constructor and field initializers also run before every test, so simple setup works there too. Prefer @BeforeEach when setup needs framework features (like injected parameters) or should run as the documented lifecycle step; use the constructor for plain field assignment.
solid answer
~50 sUnder JUnit 5's default PER_METHOD lifecycle, a fresh test-class instance is created for each test, so the constructor and field initializers run once per test — just like @BeforeEach. For simple, self-contained field setup, either works. Choose @BeforeEach when: you need JUnit's parameter resolution (e.g. an injected TestInfo or extension-provided dependency, which @BeforeEach methods can receive but constructors get only via ParameterResolver too), when setup must run after extension callbacks like @ExtendWith-provided state, or when you want setup expressed as the conventional lifecycle hook for readability and to share with subclasses via inheritance. The constructor runs before any @BeforeEach and before extension BeforeEach callbacks, so state that depends on extensions (mocks injected by MockitoExtension, Spring context) must be in @BeforeEach, not the constructor. For PER_CLASS lifecycle the constructor runs only once, so per-test setup must use @BeforeEach. As a rule: constructor for trivial wiring, @BeforeEach for anything lifecycle- or extension-dependent.
code
java · 20 linesimport org.junit.jupiter.api.*;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.*;
import org.mockito.junit.jupiter.MockitoExtension;
@ExtendWith(MockitoExtension.class)
class OrderServiceTest {
// Fine in a field initializer: trivial, no dependencies.
private final List<String> log = new ArrayList<>();
@Mock Repository repo; // injected by the extension AFTER the constructor
OrderService service;
// MUST be @BeforeEach: 'repo' does not exist yet in the constructor.
@BeforeEach
void setUp() {
service = new OrderService(repo);
log.clear();
}
}go deeper
Knows @BeforeEach is the usual place for setup and that JUnit makes a fresh instance per test.
Explains that the constructor also runs per test under PER_METHOD, and that extension-injected state forces setup into @BeforeEach.
Reasons about lifecycle ordering (constructor vs extension callbacks vs @BeforeEach), PER_CLASS differences, and final-field cleanliness vs lifecycle integration.
Guides team conventions on fixture construction, ensures setup composes correctly with extensions (Mockito/Spring) and both instance lifecycles, and avoids subtle ordering bugs.
## The surprising overlap Beginners often think `@BeforeEach` is the *only* place to set up per-test state. But under JUnit 5's **default `PER_METHOD` lifecycle**, JUnit constructs a **new instance of the test class for every `@Test` method**. That means the **constructor** and any **field initializers** *also run before every test* — they're effectively a per-test setup step too. So for plain field assignment, `new Calculator()` in a field initializer, in the constructor, or in `@BeforeEach` all run equally often (once per test). The execution order for a single test is: ``` constructor (+ field initializers) → extension BeforeEach callbacks (e.g. injected mocks) → @BeforeEach methods → @Test → @AfterEach → extension AfterEach callbacks ``` ## When the constructor is fine If your setup is **self-contained** — just creating objects from constructor arguments you control — the constructor or a field initializer is perfectly valid and arguably cleaner (the field can be `final`). Example: `private final Stack<Integer> stack = new Stack<>();`. ## When you must use @BeforeEach 1. **Extension-provided state.** Frameworks that hook the lifecycle via **`@ExtendWith`** (e.g. Mockito's `MockitoExtension` injecting `@Mock` fields, or Spring's context) populate their state in *BeforeEach extension callbacks*, which run **after** the constructor. If your setup depends on an injected mock or a wired Spring bean, doing it in the constructor is too early — the mock isn't created yet. It must go in `@BeforeEach`. 2. **Parameter injection.** `@BeforeEach` methods can declare parameters resolved by JUnit (e.g. `TestInfo`, `TestReporter`, or extension-provided objects). While constructors can also receive injected params via a `ParameterResolver`, `@BeforeEach` is the idiomatic place for setup that uses, say, the current test's `TestInfo`. 3. **PER_CLASS lifecycle.** With `@TestInstance(PER_CLASS)`, the **constructor runs only once** for the whole class. Any state that must be fresh per test then *cannot* live in the constructor — it must be in `@BeforeEach`. 4. **Inheritance and convention.** Lifecycle methods are inherited and run in a defined super-before-sub order, making `@BeforeEach` the natural place for shared base-class setup. It also signals intent: readers expect setup in `@BeforeEach`. 5. **Setup that can throw checked exceptions or needs ordering with other lifecycle hooks.** `@BeforeEach` integrates with the documented lifecycle (and `@AfterEach` teardown) more cleanly than constructor logic. ## A practical guideline - **Trivial, dependency-free field creation** → field initializer or constructor (can be `final`, clear). - **Anything depending on extensions/mocks/injected context, or needing per-test freshness under PER_CLASS, or shared via inheritance** → `@BeforeEach`. When in doubt, `@BeforeEach` is the safe, conventional default because it always runs at the right point in the lifecycle (after extensions) and behaves correctly under both instance lifecycles. ## Teardown note There is **no** symmetric 'destructor' in Java, so cleanup has only one home: **`@AfterEach`** (and `@AfterAll`). You cannot rely on finalization for test teardown, which is another reason setup that allocates resources is best paired with `@BeforeEach`/`@AfterEach`.
- With MockitoExtension, why can't you build the object-under-test in the constructor using a @Mock field?The extension injects @Mock fields in a BeforeEach callback that runs after the test-class constructor, so during the constructor the mock is still null. You must construct the object-under-test in @BeforeEach, after the mocks have been injected.
- Under PER_METHOD lifecycle, does the constructor run once or once per test?Once per test. JUnit creates a fresh test-class instance for each @Test method, so the constructor and field initializers execute before every test, just like @BeforeEach.
saying these in an interview costs you the question
- Initializing injected @Mock-dependent state in the constructor (too early)
- Believing @BeforeEach runs more often than the constructor under PER_METHOD
- Assuming the constructor runs per test under PER_CLASS (it runs once)
- Trying to do teardown in a 'destructor' instead of @AfterEach