skip to content

How do you decide whether a piece of setup belongs in @BeforeAll or @BeforeEach? What's the trade-off?

level: middleimportance: must knowfreq 60%

answer

  1. BeforeAll = expensive + shareable-unchanged (once)
  2. BeforeEach = fresh per-test state (every time)
  3. Trade-off: speed (All) vs isolation (Each)
  4. Hybrid: start in BeforeAll, reset in BeforeEach
  5. Default to BeforeEach, promote only when proven cheap-to-share

basics

~20 s

Put setup in @BeforeAll if it's expensive and the same for every test and safe to share (it runs once). Put it in @BeforeEach if each test needs its own fresh copy (it runs every time). The trade-off is speed (BeforeAll) versus isolation (BeforeEach).

solid answer

~50 s

I ask two questions. First, is the setup expensive and reusable without being changed by tests? If yes, @BeforeAll runs it once and saves time — think starting a database or server. Second, does each test need fresh, isolated state it might mutate? If yes, @BeforeEach gives every test its own clean copy, preventing cross-test pollution. The fundamental trade-off is speed versus isolation: @BeforeAll is fast because it runs once but shares state, so tests can interfere; @BeforeEach is isolated because it rebuilds per test but costs more time. The common, robust combination is both: start the expensive shared resource in @BeforeAll, then reset the small mutable state in @BeforeEach. When in doubt I default to @BeforeEach for correctness and only promote to @BeforeAll once I've confirmed the setup is read-only/shareable and the cost actually matters.

go deeper

for a junior

Knows @BeforeAll runs once and @BeforeEach runs per test, and can pick based on 'shared vs fresh'.

for a middle

Articulates the speed-vs-isolation trade-off and uses the hybrid pattern correctly.

for a senior

Defaults to isolation, promotes to @BeforeAll deliberately, and spots mutable-shared-state flakiness in review.

for a principal

Sets team conventions on fixture cost vs isolation, factoring in parallel execution and suite-wide test speed budgets.

## The decision in one sentence Use **`@BeforeAll`** when setup is **expensive AND shareable unchanged**; use **`@BeforeEach`** when each test needs **fresh, isolated state**. They're not rivals — you often use both. ## Recall the mechanics - `@BeforeAll` runs **once per class** (so it must be `static` under the default lifecycle). - `@BeforeEach` runs **once per test method** (instance method). ## The two questions to ask 1. **Is it expensive?** Starting a database container, an embedded server, a big in-memory structure, or a thread pool costs real time. Doing it per test (`@BeforeEach`) multiplies that cost by the number of tests. 2. **Is it safe to share unchanged?** If tests only *read* it, sharing is fine. If tests *mutate* it (insert rows, change fields), sharing causes one test's changes to leak into the next. | Expensive? | Mutated by tests? | Put it in | |---|---|---| | No | Yes | `@BeforeEach` (cheap to rebuild, needs isolation) | | No | No | Either; `@BeforeEach` is the safe default | | Yes | No | `@BeforeAll` (do the costly work once) | | Yes | Yes | `@BeforeAll` for the resource + `@BeforeEach` to reset state | ## The core trade-off: speed vs isolation - **`@BeforeAll` = speed, less isolation.** One setup shared by all → fast, but mutable shared state can make tests **order-dependent and flaky**. - **`@BeforeEach` = isolation, more time.** Fresh state per test → independent tests, but you repeat the work N times. ## The robust hybrid Start the **expensive, stable** thing once in `@BeforeAll` (e.g. the database engine), then in `@BeforeEach` do the **cheap reset** of the **mutable** part (e.g. truncate tables / open a fresh transaction). You get most of the speed and keep isolation. ## A good default heuristic When unsure, **prefer `@BeforeEach`** — correctness and isolation first. Only **promote to `@BeforeAll`** once you've verified the setup is genuinely read-only/shareable and its cost is worth optimizing. Premature use of `@BeforeAll` for mutable state is a classic source of flaky tests. ## Don't forget Whatever you start in `@BeforeAll`, release in `@AfterAll`; whatever you allocate per test in `@BeforeEach`, clean up in `@AfterEach` if needed.

  • You have a 2-second-to-start server but each test needs an empty database. Where does each part go?
    Start the server once in @BeforeAll (expensive, shareable) and empty/reset the database per test in @BeforeEach (cheap, needs isolation). That's the hybrid pattern: shared expensive resource plus per-test state reset.
  • Why default to @BeforeEach when unsure?
    Because isolation/correctness is the safer default; @BeforeEach guarantees each test a clean slate. You only lose some speed, which you can reclaim by promoting proven read-only setup to @BeforeAll. Defaulting to @BeforeAll risks subtle order-dependent flakiness.

saying these in an interview costs you the question

  • Using @BeforeAll for mutable per-test state
  • Using @BeforeEach for a costly shared resource that's never mutated
  • Claiming @BeforeAll is always better because it's faster
  • Forgetting that @BeforeAll's shared state survives between tests

context