In Maven projects, I have some existing tests relying on JUnit 4. I cannot migrate these tests in JUnit 5 for multiple reasons.
Essentially, some tests depend on a library which uses JUnit 4 runner and code migration may take time.
I would like all the same create new test classes with JUnit 5 that is now released and provides new interesting features.
How to do that ?
You can migrate tests written in JUnit 4 to JUnit 5 with minimal effort. Here are the steps to perform the migration: The JUnit Vintage engine in JUnit 5 helps in running existing test cases written in JUnit 4 (or JUnit 3) utilizing the JUnit Platform.
JUnit 5 provides a way out of the box. Each one is a distinct project and using all of them allows to compile and execute JUnit 4 and JUnit 5 tests in a same project.
Only one test runner can execute tests at a time in JUnit 4 (e.g. SpringJUnit4ClassRunner or Parameterized ). JUnit 5 allows multiple runners to work simultaneously. JUnit 4 never advanced beyond Java 7, missing out on a lot of features from Java 8. JUnit 5 makes good use of the Java 8 features.
How to run JUnit 5 Tests in Parallel? Yes, in this post, I will explain to you how to use JUnit 5 Parallel Test Execution feature. This is an experimental feature of JUnit 5 and it will come from after JUnit 5.3. To enable parallel execution, simply set the junit.
JUnit 5 provides a way out of the box.
JUnit 5 = JUnit Platform + JUnit Jupiter + JUnit Vintage
Each one is a distinct project and using all of them allows to compile and execute JUnit 4 and JUnit 5 tests in a same project.
JUnit Jupiter is the combination of the new programming model and extension model for writing tests and extensions in JUnit 5.
JUnit Vintage provides a TestEngine for running JUnit 3 and JUnit 4 based tests on the platform.
The JUnit Platform serves as a foundation for launching testing frameworks on the JVM
Update : from Maven Surefire 2.22.0
From the JUnit 5 documentation :
Starting with version
2.22.0
, Maven Surefire provides native support for executing tests on the JUnit Platform.
So the configuration is much simpler.
Note that the junit-4
api dependency is optional as the engine
dependencies that are now required already pull a default api
version (it is the case for both junit 4 and 5).
Here is a sample pom.xml
.
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>david</groupId> <artifactId>jupiter-4-and-5-same-build</artifactId> <version>0.0.1-SNAPSHOT</version> <properties> <maven.compiler.source>1.8</maven.compiler.source> <maven.compiler.target>1.8</maven.compiler.target> <junit-jupiter.version>5.1.0</junit-jupiter.version> <!-- optional : if we want to use a junit4 specific version --> <junit.version>4.12</junit.version> </properties> <dependencies> <!--JUnit Jupiter Engine to depend on the JUnit5 engine and JUnit 5 API --> <dependency> <groupId>org.junit.jupiter</groupId> <artifactId>junit-jupiter-engine</artifactId> <version>${junit-jupiter.version}</version> <scope>test</scope> </dependency> <!--JUnit Jupiter Engine to depend on the JUnit4 engine and JUnit 4 API --> <dependency> <groupId>org.junit.vintage</groupId> <artifactId>junit-vintage-engine</artifactId> <version>${junit-jupiter.version}</version> </dependency> <!-- Optional : override the JUnit 4 API version provided by junit-vintage-engine --> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>${junit.version}</version> <scope>test</scope> </dependency> </dependencies> <build> <plugins> <plugin> <artifactId>maven-surefire-plugin</artifactId> <version>2.22.0</version> </plugin> </plugins> </build> </project>
On my GitHub space I added a working sample maven project that you can browse/clone. URL: https://github.com/ebundy/junit4-and-5-minimal-maven-project
Old way : for Maven Surefire below 2.22.0
Here is the minimal configuration to use with Maven to configure the project to compile and run both JUnit4 and JUnit5 tests :
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>mygroup</groupId> <artifactId>minimal-conf-junit4-5</artifactId> <version>0.0.1-SNAPSHOT</version> <properties> <!-- JUnit 5 depends on JDK 1.8 --> <maven.compiler.source>1.8</maven.compiler.source> <maven.compiler.target>1.8</maven.compiler.target> <!-- JUnit dependency versions --> <junit.version>4.12</junit.version> <junit-vintage-engine>4.12.1</junit-vintage-engine> <junit-jupiter.version>5.0.1</junit-jupiter.version> <junit-platform.version>1.0.1</junit-platform.version> </properties> <dependencies> <!--JUnit Jupiter API to write and compile tests with JUnit5 --> <dependency> <groupId>org.junit.jupiter</groupId> <artifactId>junit-jupiter-api</artifactId> <version>${junit-jupiter.version}</version> <scope>test</scope> </dependency> <!-- JUnit 4 to make legacy JUnit 4 tests compile --> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>${junit.version}</version> <scope>test</scope> </dependency> </dependencies> <build> <plugins> <plugin> <artifactId>maven-surefire-plugin</artifactId> <version>2.19.1</version> <!-- matters until now--> <dependencies> <!-- to let surefire to run JUnit 4 but also JUnit 5 tests --> <dependency> <groupId>org.junit.platform</groupId> <artifactId>junit-platform-surefire-provider</artifactId> <version>${junit-platform.version}</version> </dependency> <!-- JUnit vintage engine to run JUnit 3 or JUnit 4 tests --> <dependency> <groupId>org.junit.vintage</groupId> <artifactId>junit-vintage-engine</artifactId> <version>${junit-vintage-engine}</version> </dependency> <!-- JUnit 5 engine to run JUnit 5 tests --> <dependency> <groupId>org.junit.jupiter</groupId> <artifactId>junit-jupiter-engine</artifactId> <version>${junit-jupiter.version}</version> </dependency> </dependencies> </plugin> </plugins> </build> </project>
Now mvn test
compiles and runs both JUnit 4 and JUnit 5 tests.
Note 1 : the junit-vintage-engine
(4.12.1
) and the junit
(4.12
) dependencies don't specify the same exact version.
This is not an issue at all as :
their release are not related between them
junit-vintage-engine
is designed to run any JUnit 3 or 4 tests.
Note 2 : maven-surefire-plugin with the 2.19.1
version matters whatever you want to compile JUnit 5 test classes or both JUnit 4 and JUnit 5 test classes.
Next version of the plugin causes indeed some exceptions during JUnit 5 tests execution but the 2.22.0
that at last solves the issue (see the first part of the answer : "Update : from Maven Surefire 2.22.0").
JUnit have a number of example projects at https://github.com/junit-team/junit5-samples
I had a Gradle project and following https://github.com/junit-team/junit5-samples/tree/main/junit5-migration-gradle worked for me.
https://github.com/junit-team/junit5-samples/tree/main/junit5-migration-maven is the Maven equivalent - I have not tried it but I imagine that it works too.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With