skip to content

What is JUnit 5's @Nested annotation, and why would you use it to organize your tests?

level: juniorimportance: should knowfreq 45%

answer

  1. Annotation on a non-static inner class
  2. Groups tests by scenario/state
  3. Mirrors structure, removes duplicate setup
  4. Readable indented report with @DisplayName
  5. Organizational, not behavioral

basics

~20 s

@Nested marks an inner test class inside another test class. It groups related tests together so you can express scenarios like 'when the cart is empty' as their own block with their own setup, making tests easier to read and organize.

solid answer

~40 s

@Nested is a JUnit 5 annotation placed on a non-static inner class to group related test methods inside an enclosing test class. It lets you mirror the structure of the thing you're testing — for example one nested class per scenario or per state (empty list vs populated list). Each nested class can have its own @BeforeEach setup and its own @DisplayName, so the test report reads like nested sentences ('Stack > when new > is empty'). Because the inner class is non-static, it can access the outer instance's fields and helper methods, sharing context. Nesting improves readability and removes duplication: shared arrangement lives in the parent, scenario-specific arrangement lives in the child. It's purely organizational — it doesn't change what is tested, only how tests are grouped and reported.

code

java · 15 lines
java
class StackTest {
    Deque<String> stack;

    @Nested
    @DisplayName("when new")
    class WhenNew {
        @BeforeEach
        void create() { stack = new ArrayDeque<>(); }

        @Test
        void isEmpty() {
            assertTrue(stack.isEmpty());
        }
    }
}

go deeper

for a junior

Knows @Nested groups related tests into an inner class to improve readability and that it's organizational, not behavioral.

for a middle

Can explain the non-static requirement and how it enables shared outer-instance state, and pairs it with @DisplayName for readable reports.

for a senior

Designs nested hierarchies that mirror the system under test, layering setup to remove duplication and keep each scenario's arrangement local.

for a principal

Sets team conventions for test structure (scenario-per-nested-class), weighs readability vs over-nesting, and ensures the approach scales across a large suite.

## What @Nested is **JUnit 5** (also called JUnit Jupiter) is the standard unit-testing framework for Java. A **unit test** is a small piece of code that verifies one behavior of your program by calling it and asserting (checking) the result. You write test methods, each marked with `@Test`, inside a **test class**. As a test class grows, all its `@Test` methods sit flat at the same level, which becomes hard to read. **`@Nested`** is an annotation you put on an **inner class** declared *inside* your test class to create a sub-group of tests. (An **annotation** is metadata written with `@`, e.g. `@Test`, that the framework reads to decide how to treat the code. An **inner class** is a class defined inside another class.) ## Why group tests A single behavior often depends on context: "when the account has funds" vs "when it's overdrawn". With `@Nested` you create one inner class per context, and put the tests for that context inside it. This: - **Mirrors structure** — the test layout matches the scenarios you're describing. - **Reduces duplication** — common setup (arranging objects) goes in the outer class; each nested class only adds what's specific to its scenario. - **Produces readable reports** — combined with `@DisplayName` (a human-readable label), runners and IDEs show an indented tree like `BankAccount > when overdrawn > rejects a withdrawal`. ## Minimal example ```java class StackTest { Deque<String> stack; @Nested class WhenNew { @BeforeEach void create() { stack = new ArrayDeque<>(); } @Test void isEmpty() { assertTrue(stack.isEmpty()); } } } ``` Here `WhenNew` is a `@Nested` class describing the "freshly created" scenario. Its `@BeforeEach` (a method that runs before each test) builds the stack; its `@Test` checks the stack starts empty. ## Key rule: must be non-static The nested class must be a **non-static inner class** (not declared `static`). A non-static inner class holds a hidden reference to an instance of its enclosing class, so its methods can read the outer class's fields (`stack` above) and call its helpers. JUnit relies on this to share context from parent to child. If you mark the class `static`, JUnit will not treat it as a `@Nested` test group the same way (a static nested class is independent and loses the shared-instance link). ## It's organizational only `@Nested` changes *how tests are grouped and displayed*, not *what* is verified. The same assertions would pass or fail identically in a flat layout; nesting just makes intent and structure clearer and keeps shared setup in one place.

  • Does @Nested change which assertions run or only how they're grouped?
    Only how they're grouped and reported. The assertions themselves run identically; nesting is purely organizational and improves readability plus setup reuse.
  • Why pair @Nested with @DisplayName?
    @DisplayName gives each nested class and test a human-readable label, so the runner shows a readable sentence-like tree (e.g. 'Stack > when new > is empty') instead of class/method names.

Like chapters and sub-sections in a book: the outer class is the chapter, each @Nested class is a sub-section grouping closely related paragraphs (tests) under a shared heading.

saying these in an interview costs you the question

  • Thinking @Nested runs tests in parallel or changes execution semantics — it's organizational.
  • Believing nested test classes must be declared static (they must be non-static).
  • Confusing @Nested (grouping) with parameterized tests (data-driven repetition).

context