Category Archives: JUnit

JUnit 6

JUnit 6 represents the next evolution in Java testing, building on the solid foundation of JUnit 5 while introducing modern features, improved API design, and enhanced developer experience. Whether you’re upgrading from JUnit 5 or starting fresh, this comprehensive guide covers everything you need to know about JUnit 6β€”from core concepts to advanced patterns.

Why JUnit 6?

JUnit 6 continues the modular architecture introduced in JUnit 5, with refinements focused on reducing cognitive load, improving discoverability, and providing better integration with modern Java features like records, sealed classes, and virtual threads. The framework emphasizes backward compatibility while offering clear upgrade paths for existing projects.

Getting Started with JUnit 6

Before diving into advanced topics, get acquainted with the fundamentals of JUnit 6.

Core Testing Patterns

Master the essential patterns that form the foundation of professional test suites.

Mocking and Test Doubles

Integrate popular mocking frameworks with JUnit 6 for effective unit testing in isolation.

Extensions and Customization

Extend JUnit 6 with custom extensions for specialized testing needs.

Integration Testing

Combine JUnit 6 with Spring and other frameworks for comprehensive integration tests.

Performance and Best Practices

Optimize your tests for speed and maintainability.

Troubleshooting and Quality

Learn what to watch out for and how to solve common problems.

Advanced Topics

Deep dives into specialized scenarios and cutting-edge patterns.

AI Prompts for JUnit 6

Use AI tools to accelerate your JUnit 6 testing workflow.

Quick Reference

Key Annotations: @Test, @DisplayName, @BeforeEach, @AfterEach, @BeforeAll, @AfterAll, @ParameterizedTest, @RepeatedTest, @Nested, @Disabled, @EnabledOnJava, @EnabledOnOs

Common Assertions: assertEquals, assertNotEquals, assertTrue, assertFalse, assertNull, assertNotNull, assertSame, assertArrayEquals, assertIterableEquals, assertThrows, assertDoesNotThrow, assertAll

Extension Points: BeforeAllCallback, AfterAllCallback, BeforeEachCallback, AfterEachCallback, BeforeTestExecutionCallback, AfterTestExecutionCallback, TestInstancePostProcessor, ParameterResolver, TestTemplateInvocationContextProvider

Next Steps

JUnit 6 provides a comprehensive, modular foundation for testing Java applications of any size. Whether you’re writing unit tests for a small utility, integration tests for a microservice, or full test suites for enterprise systems, JUnit 6’s flexible extension model and rich feature set help you write clear, maintainable tests that improve code quality and accelerate development.

Start with the fundamentals, master the core patterns, and progressively adopt advanced techniques as your testing needs grow. The investment in learning JUnit 6 thoroughly pays dividends in every project you build.

Modern Java Testing: JUnit 6 + AssertJ + Mockito 5 + Testcontainers

JUnit 6 is the first major JUnit release built for Java 17+ and the virtual-thread era. But JUnit alone is only the runner β€” modern Java test suites pair it with AssertJ for fluent assertions, Mockito 5 for mocking, and Testcontainers for real infrastructure in integration tests. This post ties all four together into a complete, runnable example you can drop into any Spring Boot or plain-Java project.

Continue reading Modern Java Testing: JUnit 6 + AssertJ + Mockito 5 + Testcontainers

JUnit 6 Nullability: @Nullable, @NonNull and @NullMarked Explained

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.

Continue reading JUnit 6 Nullability: @Nullable, @NonNull and @NullMarked Explained

10 AI Prompts to Debug and Fix JUnit 6 Test Failures

The test failure that taught me to write better debugging prompts was a flaky integration test that failed roughly one CI run in five. I pasted the assertion error into an AI assistant and got back five generic guesses, none right. Then I pasted the complete picture β€” full stack trace, the whole test class, the production method, and the fact that it only failed in parallel runs β€” and the diagnosis (shared static state in a test fixture) came back in one reply. The lesson: with debugging, the prompt is mostly evidence collection.

This post collects 10 prompts for diagnosing and fixing broken, flaky, or misbehaving JUnit 6 tests, each structured around the evidence that particular failure type needs β€” so the AI diagnoses the root cause instead of guessing. Tested with Claude Sonnet 4 and GPT-4o against JUnit 6.0, Mockito 5.x, and Spring Boot 3.4 failures.

For complementary reading, see Debugging JUnit 6 Tests: Fix Failures Like a Pro and How to Fix Flaky Tests in JUnit 6.

Continue reading 10 AI Prompts to Debug and Fix JUnit 6 Test Failures

10 AI Prompts to Optimise and Update Existing JUnit 6 Tests

Existing test suites accumulate technical debt just like production code. Tests that were written quickly become brittle, slow, hard to read, or duplicated. Optimising and updating your JUnit 6 tests is not just housekeeping β€” it directly determines whether your test suite remains a trusted safety net or becomes a maintenance burden that developers work around.

This post gives you 10 targeted AI prompts designed to refactor, improve, and modernise existing JUnit 6 test code. Each prompt addresses a specific quality problem β€” from brittle mocking to slow Spring contexts to missing boundary cases β€” and produces immediately usable improved test code.

For foundational context, see Writing Maintainable Tests in JUnit 6 and Refactoring Legacy Tests to JUnit 6.

Continue reading 10 AI Prompts to Optimise and Update Existing JUnit 6 Tests

10 AI Prompts to Generate JUnit 6 Tests for New Projects

The first time I asked an AI assistant to generate tests for a service class, it gave me fifteen green tests that verified almost nothing β€” assertNotNull on every line, mocks returning values no production system would produce, and not a single boundary case. The tests passed; they just didn’t protect anything. What changed the output quality wasn’t a better model β€” it was a better prompt: one that pinned the JUnit version, demanded specific annotations, listed the scenarios that had to be covered, and forced meaningful assertions.

This post collects the 10 prompts for generating JUnit 6 tests that came out of that process β€” refined across real projects until the output was something I could commit after a review pass rather than a rewrite. They work with GitHub Copilot, Claude, ChatGPT, JetBrains AI, or any capable LLM. Tested against Claude Sonnet 4 and GPT-4o, generating tests for JUnit 6.0 with Mockito 5.x and Spring Boot 3.4.

For background on JUnit 6 test structure, see the JUnit 6 Tutorial Series. For best practices on what makes a test maintainable, see Writing Your First Clean Test in JUnit 6.

Continue reading 10 AI Prompts to Generate JUnit 6 Tests for New Projects

JUnit 6 vs Spock vs TestNG: Best Testing Framework for Java?

If you are choosing a testing framework for a new Java project β€” or evaluating whether to migrate an existing one β€” you need an honest, detailed comparison of all three major options. JUnit 6, Spock, and TestNG each have genuine strengths and real trade-offs. This guide compares them across every dimension that matters: syntax, features, performance, ecosystem, and team fit.

Framework Profiles

Before diving into code, it helps to understand each framework at a high level. JUnit 6 is the direct evolution of the most widely used Java testing library in history, built on a clean three-module architecture. Spock takes a fundamentally different approach β€” it is written in Groovy and embraces a specification-style, BDD-inspired syntax that many developers find more expressive than annotation-driven frameworks. TestNG was created to address limitations in early JUnit versions and remains popular for its advanced grouping, parallel execution, and test dependency features. The table below captures the most important dimensions at a glance before we explore each in depth.

JUnit 6SpockTestNG
LanguageJavaGroovy (runs on JVM)Java
First release1997 (JUnit 1)20082004
ParadigmAnnotation-drivenSpecification-based (BDD)Annotation-driven
MockingSeparate (Mockito)Built-in (Spock Mocks)Separate (Mockito)
Spring Boot supportNative, first-classVia spock-springManual config
Learning curveLow (Java devs)Medium (need Groovy)Low (Java devs)

Syntax Comparison: The Same Test in All Three

The most revealing comparison is seeing exactly the same test case written in each framework side by side. All three examples below test the same behaviour: placing a valid order should save it via the repository and return an order with CONFIRMED status. Pay attention to how each framework handles the test structure, mock setup, and verification β€” the differences in verbosity and readability are immediately apparent and reflect each framework’s core design philosophy.

Continue reading JUnit 6 vs Spock vs TestNG: Best Testing Framework for Java?