Introduction
JUnit 5 is a complete rewrite of the JUnit testing framework for Java and the JVM. It introduces a modular architecture that separates the test engine from the platform, enabling support for multiple testing styles and third-party extensions while maintaining backward compatibility with JUnit 4 tests.
What JUnit 5 Does
- Provides annotations like @Test, @BeforeEach, @ParameterizedTest, and @Nested for structured test organization
- Supports parameterized tests with CSV, enum, method, and custom argument sources
- Offers a powerful extension model for dependency injection, lifecycle callbacks, and conditional test execution
- Runs on the JUnit Platform which supports multiple test engines simultaneously
- Maintains backward compatibility with JUnit 4 tests via the Vintage engine
Architecture Overview
JUnit 5 is composed of three modules: JUnit Platform provides the foundation for launching test frameworks on the JVM and defines the TestEngine API. JUnit Jupiter supplies the new programming model and extension model for writing tests. JUnit Vintage enables running JUnit 3 and 4 tests on the platform. This separation allows IDEs and build tools to support any test engine that implements the platform API, including third-party engines like Spock and TestNG adapters.
Self-Hosting & Configuration
- Add
junit-jupiteras a test dependency in Maven or Gradle to get the full Jupiter API and engine - Configure test execution in Gradle with
useJUnitPlatform()in the test task - Use
junit-platform.propertieson the classpath to set default parallel execution and display name generators - Enable parallel test execution with
junit.jupiter.execution.parallel.enabled = true - Integrate with CI by relying on standard Maven Surefire or Gradle test tasks that support JUnit Platform natively
Key Features
- @ParameterizedTest with @CsvSource, @MethodSource, and @EnumSource for data-driven testing
- @Nested inner classes for hierarchical, BDD-style test organization
- Dynamic tests via @TestFactory for generating test cases at runtime
- Conditional test execution based on OS, JRE version, environment variables, or custom conditions
- Extensible via the Extension API for custom lifecycle hooks, parameter resolvers, and test templates
Comparison with Similar Tools
- JUnit 4 — predecessor with a monolithic architecture; JUnit 5 is modular and more extensible
- TestNG — XML-driven configuration and built-in parallelism; JUnit 5 now matches these features with annotations
- Spock — Groovy-based BDD framework; JUnit 5 Nested classes offer similar structure in pure Java
- Mockito — mocking library; complements JUnit 5 with the MockitoExtension for dependency injection
- AssertJ — fluent assertions library; pairs well with JUnit 5 as a drop-in replacement for built-in assertions
FAQ
Q: Can I run JUnit 4 and JUnit 5 tests together? A: Yes. Add the junit-vintage-engine dependency and both JUnit 4 and JUnit 5 tests run on the same JUnit Platform.
Q: How do I run tests in parallel?
A: Set junit.jupiter.execution.parallel.enabled=true and junit.jupiter.execution.parallel.mode.default=concurrent in junit-platform.properties.
Q: Does JUnit 5 support Kotlin? A: Yes. JUnit 5 works seamlessly with Kotlin, and the Jupiter API's use of default methods and annotations is Kotlin-friendly.
Q: What happened to @Rule from JUnit 4? A: JUnit 5 replaces Rules with the Extension API. Most common rules have Jupiter equivalents, and a migration guide is provided in the official documentation.