junit5
✅ The 5th major version of the programmer-friendly testing framework for Java and the JVM
Top Related Projects
Most popular Mocking framework for unit tests written in Java
TestNG testing framework
The Enterprise-ready testing and specification framework.
Cucumber for the JVM
AssertJ is a library providing easy to use rich typed assertions
Java (and original) version of Hamcrest
Quick Overview
JUnit 5 is the next generation of the popular JUnit testing framework for Java. It introduces a modular approach to testing, with separate modules for the JUnit Platform, JUnit Jupiter, and JUnit Vintage. This redesign allows for better integration with IDEs and build tools, as well as support for new testing styles and extensions.
Pros
- Modular architecture allows for easier customization and extension
- Improved support for Java 8 features, including lambda expressions and method references
- Powerful parameterized tests with various sources of test data
- Better integration with IDEs and build tools
Cons
- Learning curve for developers familiar with JUnit 4
- Some legacy projects may face challenges when migrating from JUnit 4 to JUnit 5
- Requires Java 8 or higher, which may be an issue for older projects
Code Examples
- Basic test example:
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;
class SimpleTest {
@Test
void testAddition() {
assertEquals(4, 2 + 2, "2 + 2 should equal 4");
}
}
- Parameterized test example:
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.CsvSource;
import static org.junit.jupiter.api.Assertions.*;
class ParameterizedTests {
@ParameterizedTest
@CsvSource({"1, 1, 2", "2, 3, 5", "5, 5, 10"})
void testAddition(int a, int b, int expected) {
assertEquals(expected, a + b, () -> a + " + " + b + " should equal " + expected);
}
}
- Nested tests example:
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;
class NestedTests {
@Nested
class WhenPositive {
@Test
void testPositiveAddition() {
assertTrue(5 + 3 > 0, "Sum of positive numbers should be positive");
}
}
@Nested
class WhenNegative {
@Test
void testNegativeAddition() {
assertTrue(-5 + (-3) < 0, "Sum of negative numbers should be negative");
}
}
}
Getting Started
To use JUnit 5 in your project, add the following dependencies to your build file:
For Maven (pom.xml):
<dependencies>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
<version>5.9.2</version>
<scope>test</scope>
</dependency>
</dependencies>
For Gradle (build.gradle):
dependencies {
testImplementation 'org.junit.jupiter:junit-jupiter:5.9.2'
}
test {
useJUnitPlatform()
}
After adding the dependencies, you can start writing tests using the @Test
annotation in your test classes. Run the tests using your IDE's test runner or build tool's test command.
Competitor Comparisons
Most popular Mocking framework for unit tests written in Java
Pros of Mockito
- More focused on mocking and stubbing, providing a wider range of mocking capabilities
- Simpler syntax for creating mocks and defining behavior
- Better integration with other testing frameworks, including JUnit
Cons of Mockito
- Limited to mocking and stubbing, lacking the comprehensive testing features of JUnit 5
- May require additional setup and configuration when used alongside other testing frameworks
- Less extensive parameterized testing support compared to JUnit 5
Code Comparison
Mockito:
@Test
void testWithMockito() {
List mockedList = mock(List.class);
when(mockedList.get(0)).thenReturn("first");
assertEquals("first", mockedList.get(0));
}
JUnit 5:
@ParameterizedTest
@ValueSource(strings = { "racecar", "radar", "able was I ere I saw elba" })
void palindromes(String candidate) {
assertTrue(StringUtils.isPalindrome(candidate));
}
Both JUnit 5 and Mockito are essential tools for Java developers, with JUnit 5 providing a comprehensive testing framework and Mockito excelling in mocking and stubbing. While JUnit 5 offers more extensive testing features, Mockito's simplicity and focused approach to mocking make it a valuable complement to any testing suite. Developers often use both libraries together to create robust and thorough test suites for their Java applications.
TestNG testing framework
Pros of TestNG
- More flexible test configuration with XML files and annotations
- Built-in support for data-driven testing and parallel execution
- Better handling of dependencies and groups for test organization
Cons of TestNG
- Steeper learning curve compared to JUnit's simplicity
- Less widespread adoption in the Java community
- Fewer third-party integrations and plugins available
Code Comparison
TestNG example:
@Test(groups = {"fast"})
public void testMethod() {
// Test logic here
}
JUnit 5 example:
@Test
@Tag("fast")
void testMethod() {
// Test logic here
}
Both frameworks offer similar functionality for basic test cases, but TestNG provides more built-in features for complex testing scenarios. JUnit 5 has improved significantly with its modular architecture and extensibility, narrowing the gap between the two frameworks.
TestNG excels in enterprise-level testing with its powerful configuration options and parallel execution capabilities. JUnit 5, on the other hand, maintains a simpler API while introducing new features like dynamic tests and improved parameterized tests.
Ultimately, the choice between TestNG and JUnit 5 depends on project requirements, team expertise, and existing ecosystem integration.
The Enterprise-ready testing and specification framework.
Pros of Spock
- Expressive and readable test syntax using Groovy's power
- Built-in mocking and stubbing capabilities
- Data-driven testing with easy-to-use data tables
Cons of Spock
- Limited to Groovy language, not native Java
- Smaller community and ecosystem compared to JUnit
Code Comparison
Spock test:
def "maximum of two numbers"() {
expect:
Math.max(a, b) == c
where:
a | b | c
1 | 3 | 3
7 | 4 | 7
0 | 0 | 0
}
JUnit 5 test:
@ParameterizedTest
@CsvSource({"1, 3, 3", "7, 4, 7", "0, 0, 0"})
void maximumOfTwoNumbers(int a, int b, int expected) {
assertEquals(expected, Math.max(a, b));
}
Spock offers a more concise and readable syntax for data-driven tests, while JUnit 5 requires additional annotations and a less intuitive CSV format. However, JUnit 5 provides native Java support and a larger ecosystem of extensions and integrations.
Cucumber for the JVM
Pros of Cucumber JVM
- Supports Behavior-Driven Development (BDD) with Gherkin syntax
- Enables non-technical stakeholders to understand and contribute to test scenarios
- Provides better test documentation and readability
Cons of Cucumber JVM
- Steeper learning curve for developers unfamiliar with BDD concepts
- Can be slower to execute compared to JUnit 5 tests
- Requires additional setup and configuration
Code Comparison
JUnit 5:
@Test
void testAddition() {
assertEquals(4, Calculator.add(2, 2));
}
Cucumber JVM:
Scenario: Adding two numbers
Given I have entered 2 into the calculator
And I have entered 2 into the calculator
When I press add
Then the result should be 4 on the screen
public class CalculatorSteps {
@Given("I have entered {int} into the calculator")
public void enterNumber(int number) { /* ... */ }
@When("I press add")
public void pressAdd() { /* ... */ }
@Then("the result should be {int} on the screen")
public void checkResult(int expected) { /* ... */ }
}
AssertJ is a library providing easy to use rich typed assertions
Pros of AssertJ
- More fluent and readable assertions with method chaining
- Rich set of assertions for various data types and collections
- Soft assertions for multiple checks without stopping at first failure
Cons of AssertJ
- Steeper learning curve due to extensive API
- Potentially longer assertion statements compared to JUnit
Code Comparison
AssertJ:
assertThat(list).hasSize(3)
.contains("A", "B")
.doesNotContain("X");
JUnit 5:
assertEquals(3, list.size());
assertTrue(list.contains("A"));
assertTrue(list.contains("B"));
assertFalse(list.contains("X"));
Key Differences
- AssertJ focuses on fluent, expressive assertions
- JUnit 5 provides a broader testing framework with lifecycle management
- AssertJ offers more specialized assertions for different data types
- JUnit 5 has built-in support for parameterized tests and dynamic tests
Use Cases
- Use AssertJ for projects requiring detailed, expressive assertions
- Choose JUnit 5 for a comprehensive testing framework with simpler assertions
- Combine both: Use JUnit 5 as the test runner with AssertJ for assertions
Java (and original) version of Hamcrest
Pros of JavaHamcrest
- More flexible and expressive assertion syntax
- Easier to create custom matchers
- Better readability for complex assertions
Cons of JavaHamcrest
- Steeper learning curve for beginners
- Less integrated with modern Java features
- Requires additional dependency management
Code Comparison
JavaHamcrest:
assertThat(actual, is(equalTo(expected)));
assertThat(list, hasItems("item1", "item2"));
assertThat(object, hasProperty("name", equalTo("John")));
JUnit 5:
assertEquals(expected, actual);
assertTrue(list.contains("item1") && list.contains("item2"));
assertEquals("John", object.getName());
Summary
JavaHamcrest offers a more expressive and flexible assertion syntax, making it easier to create custom matchers and write readable complex assertions. However, it has a steeper learning curve and requires additional dependency management compared to JUnit 5.
JUnit 5, on the other hand, provides a more straightforward approach with built-in assertions that are easier for beginners to grasp. It also integrates better with modern Java features and has a simpler setup process.
The choice between the two depends on the project's complexity, team expertise, and specific testing requirements. Many developers use both libraries together to leverage the strengths of each.
Convert designs to code with AI
Introducing Visual Copilot: A new AI model to turn Figma designs to high quality code using your components.
Try Visual CopilotREADME
JUnit 5
This repository is the home of JUnit 5.
Sponsors
- Gold Sponsors: JetBrains
- Silver Sponsors: Micromata, Quo Card
- Bronze Sponsors: Premium Minds, Testmo, codefortynine, Info Support, Stiltsoft, Code Intelligence, Route4Me
Latest Releases
- General Availability (GA): JUnit 5.11.0 (August 14, 2024)
- Preview (Milestone/Release Candidate): N/A
Documentation
Contributing
Contributions to JUnit 5 are both welcomed and appreciated. For specific guidelines
regarding contributions, please see CONTRIBUTING.md in the root directory of the
project. Those willing to use milestone or SNAPSHOT releases are encouraged
to file feature requests and bug reports using the project's
issue tracker. Issues marked with an
up-for-grabs
label are specifically targeted for community contributions.
Getting Help
Ask JUnit 5 related questions on StackOverflow or chat with the community on Gitter.
Continuous Integration Builds
Official CI build server for JUnit 5. Used to perform quick checks on submitted pull requests and for build matrices including the latest released OpenJDK and early access builds of the next OpenJDK.
Code Coverage
Code coverage using JaCoCo for the latest build is available on Codecov.
A code coverage report can also be generated locally via the Gradle Wrapper by
executing ./gradlew -Ptesting.enableJaCoCo clean jacocoRootReport
. The results will be available
in build/reports/jacoco/jacocoRootReport/html/index.html
.
Develocity
JUnit 5 utilizes Develocity for Build Scans, Build Cache, and Predictive Test Selection.
The latest Build Scans are available on ge.junit.org. Currently,
only core team members can publish Build Scans on that server.
You can, however, publish a Build Scan to scans.gradle.com by
using the --scan
parameter explicitly.
The remote Build Cache is enabled by default for everyone so that local builds can reuse task outputs from previous CI builds.
Building from Source
You need JDK 21 to build JUnit 5. Gradle toolchains are used to detect and potentially download additional JDKs for compilation and test execution.
All modules can be built and tested with the Gradle Wrapper using the following command.
./gradlew build
Installing in Local Maven Repository
All modules can be installed with the Gradle Wrapper in a local Maven repository for consumption in other projects via the following command.
./gradlew publishToMavenLocal
Dependency Metadata
Consult the Dependency Metadata section of the User Guide for a list of all artifacts of the JUnit Platform, JUnit Jupiter, and JUnit Vintage.
See also https://repo1.maven.org/maven2/org/junit/ for releases and https://oss.sonatype.org/content/repositories/snapshots/org/junit/ for snapshots.
Top Related Projects
Most popular Mocking framework for unit tests written in Java
TestNG testing framework
The Enterprise-ready testing and specification framework.
Cucumber for the JVM
AssertJ is a library providing easy to use rich typed assertions
Java (and original) version of Hamcrest
Convert designs to code with AI
Introducing Visual Copilot: A new AI model to turn Figma designs to high quality code using your components.
Try Visual Copilot