JUnit 6 adopted JSpecify nullability annotations across its entire API surface. Every method parameter, return type, and field in JUnit’s public API is now explicitly annotated to declare whether it can be null. The result is stronger IDE guidance, better static analysis, and safer Kotlin interop β all without changing how your tests run.
This guide explains the three annotations you will encounter β @Nullable, @NonNull, and @NullMarked β with complete, runnable examples for each.
Why JUnit 6 Adopted JSpecify
Before JUnit 6, the framework’s API gave no formal signal about which parameters or return values could be null. Developers relied on documentation, runtime exceptions, or convention. JUnit 6 fixed this by adopting JSpecify β a vendor-neutral, standardised set of null-safety annotations that IDEs (IntelliJ, Eclipse), static analysers (NullAway, Error Prone, SpotBugs), and Kotlin’s compiler all understand.
One important point to understand upfront: these annotations do not insert null checks at runtime. They are compile-time and tooling contracts. If you pass null to a @NonNull parameter at runtime, the JVM will not throw an exception at the call site β it will throw a NullPointerException only when that value is actually dereferenced. The annotations shift detection earlier, to your IDE and CI pipeline.