JUnit 5 Nested Test Class Mismatch

ID

java.junit5_inner_test_classes_annotated

Severity

high

Remediation Complexity

trivial

Remediation Risk

low

Remediation Effort

low

Resource

Reliability

Language

Java

Tags

reliability, testing

Description

Reports a member class that declares JUnit 5 test methods (@Test, @RepeatedTest, @TestFactory, @TestTemplate or @ParameterizedTest) and gets the @Nested annotation backwards: a non-static inner class missing it, or a static nested class carrying it.

Rationale

@Nested is how JUnit 5 tells an inner class from a plain member class: without it, the engine never instantiates the class and its tests silently never run, even though the class compiles and reads exactly like a working test. The opposite mistake is just as broken — @Nested on a static nested class is rejected, because a static class shares no instance state with its enclosing test, which is the entire point of nesting tests in the first place.

class OrderServiceTest {

  class PricingRules {                 // FLAW — inner test class missing @Nested

    @Test
    void appliesTierDiscount() {
      // never runs — the engine does not know this class holds tests
    }
  }

  @Nested
  static class LoyaltyRules {          // FLAW — @Nested on a static nested class

    @Test
    void awardsPoints() {
      // rejected: a static class shares no instance state with OrderServiceTest
    }
  }

  static class RefundRules {           // OK — static and unannotated

    @Test
    void refundsWithinWindow() {
    }
  }
}

Remediation

Annotate the inner class with @Nested, or drop static from a nested class that needs @Nested.

class OrderServiceTest {

  @Nested
  class PricingRules {

    @Test
    void appliesTierDiscount() {
      // runs as part of OrderServiceTest
    }
  }
}

What is not reported

An abstract member class is left alone, since it is meant to be extended rather than run directly. A local class declared inside a method body, and an anonymous class body, are both out of scope — neither is a member class JUnit 5 can discover as nested, regardless of @Nested. A class whose only test-shaped methods carry a JUnit 4 or TestNG @Test is left alone too, because @Nested has no effect on either.

This rule does not check whether the build is configured to execute static nested test classes at all (some build/test runner defaults skip them); that is a build configuration concern, not a JUnit 5 usage defect.

© 2026 Xygeni. All rights reserved