How do you use @Nested in Kotlin to group JUnit 5 tests, and what lifecycle behaviour applies to nested classes?
answer
- @Nested groups tests into a tree
- Must be `inner class` in Kotlin (non-static)
- Outer @BeforeEach runs before inner @BeforeEach
- inner gives access to enclosing instance state
- Nested @BeforeAll still needs PER_CLASS
basics
~10 sYou put related tests inside an inner class marked @Nested. JUnit runs them as a sub-group, and the inner class can access the outer class's fields, which helps share setup.
solid answer
~40 s`@org.junit.jupiter.api.Nested` marks a member class whose `@Test` methods form a logical sub-group in the report (rendered as a tree). In Kotlin the nested class must be a non-static **`inner class`**, because JUnit requires a non-static nested class so the inner instance can reach the enclosing instance and its setup. Each `@Nested` class has its own `@BeforeEach`/`@AfterEach`, and outer `@BeforeEach` runs *before* inner ones (outer-to-inner), so you can layer context. `@BeforeAll` in a nested class normally requires PER_CLASS just like at top level. A common pattern: an outer `when … (given a logged-in user)` group with several inner `@Nested` scenario classes. This reads like a BDD spec and avoids repeating shared arrange code. Without `inner`, the test class is static and JUnit will not instantiate it correctly for nesting.
code
kotlin · 14 linesimport org.junit.jupiter.api.*
import kotlin.test.assertEquals
class CalculatorTest {
private val calc = Calculator()
@Nested
inner class Division {
@Test fun `divides evenly`() { assertEquals(2, calc.div(4, 2)) }
@Test fun `throws on zero`() {
assertThrows<ArithmeticException> { calc.div(1, 0) }
}
}
}go deeper
Knows @Nested groups related tests and reports them as a tree.
Knows the Kotlin inner requirement and that nested classes get their own @BeforeEach.
Explains outer-to-inner lifecycle layering and the PER_CLASS need for nested @BeforeAll.
Guides BDD-style grouping conventions and warns against over-nesting for maintainability.
## What @Nested does `@Nested` (from `org.junit.jupiter.api.Nested`) turns a member class into a **grouped sub-suite**. The IDE and reports render it as a tree: the outer class name, then each nested class, then its tests. This expresses hierarchy — e.g. shared context with several scenarios. ## Kotlin requirement: `inner class` JUnit requires nested test classes to be **non-static**. In Kotlin, a nested class is *static by default*; you must add the **`inner`** keyword to make it hold a reference to the enclosing instance: ```kotlin import org.junit.jupiter.api.* class StackTest { private val stack = ArrayDeque<Int>() @Test fun `is empty initially`() { assert(stack.isEmpty()) } @Nested inner class AfterPushing { @BeforeEach fun push() { stack.addLast(42) } // sees outer 'stack' @Test fun `is not empty`() { assert(stack.isNotEmpty()) } @Test fun `pop returns the value`() { assertEquals(42, stack.removeLast()) } } } ``` Without `inner`, the class is static, cannot access `stack`, and JUnit will not run it as a nested test. ## Lifecycle layering (outer-to-inner) For each test inside a `@Nested` class: 1. The **outer** class's `@BeforeEach` runs first. 2. Then the **nested** class's `@BeforeEach`. 3. The test runs. 4. Nested `@AfterEach`, then outer `@AfterEach`. This lets you build context in layers (outer = base arrange, inner = scenario tweak). ## @BeforeAll in nested classes A nested class can have `@BeforeAll`, but — as everywhere — it must be static **or** the nested class must carry `@TestInstance(TestInstance.Lifecycle.PER_CLASS)`. PER_CLASS can be inherited by nested classes from the outer class default. ## When to use it - BDD-style `given/when/then` grouping. - Sharing arrange code across several related scenarios. - Producing a readable tree report instead of a flat list. Keep nesting shallow (one or two levels); deep trees hurt readability.
- What happens if you forget the `inner` keyword on a @Nested class in Kotlin?The class is static, cannot access enclosing-instance state, and JUnit will not execute it as a nested test (or errors).
- In what order do outer and inner @BeforeEach run?Outer-to-inner: the enclosing class's @BeforeEach runs first, then the nested class's, then the test.
@Nested is like chapters and sub-sections in a spec document, where each sub-section inherits the chapter's setup.
saying these in an interview costs you the question
- Forgetting that Kotlin nested classes are static unless marked `inner`
- Saying inner @BeforeEach runs before outer @BeforeEach
- Claiming @Nested classes can't have their own lifecycle methods
- Deeply nesting many levels and harming readability