This is not ment to be a complete guide on how to actually convert your application from Junit 4 to Junit 5.
This is just my own findings and ramblings, and the list is by far complete. Despite that; I hope that it may help on the way to converting your Junit 4 application to a Junit 5 application.
Plain Web Application that were using:
- Spring 4.HEAD
- Jetty 9.HEAD
- Spring Security
- Junit 4
- Mockito 1.19
- Jersey
This actually is not only tied to Junit, but also to Spring as we've used the SpringRunner with the @RunWith-annotation. So, therefor, this overview contains Spring as well as Mockito. See below
<!-- Mockito -->
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<version>2.12.0</version>
<scope>test</scope>
</dependency>
<!-- JUNIT -->
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-params</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.platform</groupId>
<artifactId>junit-platform-launcher</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apiguardian</groupId>
<artifactId>apiguardian-api</artifactId>
<version>1.0.0</version>
<scope>test</scope>
</dependency>
<!-- SPRING -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-WHATEVER</artifactId>
<version>${spring.version}</version>
</dependency>
...
...
<spring.version>5.0.1.RELEASE</spring.version>
<junit.helpers.version>5.0.2</junit.helpers.version>
So, jeah, as you may realize from the dependencies - Spring 5.x is required for Junit 5 to work. Or...that is actually not true, as you may make your own Extendor, however, we did not bother with that, so we ended up replacing Spring 4.x with Spring 5.x. As you will notice below (somewhere in this document at least); in order to get the Extendor for "free", you'll just import Spring 5.x. In Spring 5.x you'll find the following class that you can use wherever SpringJUnit4ClassRunner.class were previously used. So:
@RunWith(SpringJUnit4ClassRunner.class) => @ExtendWith(SpringExtension.class)
That should be it in regards to stuff that is required to get things to work again togetehr with Junit 5.
If you're using Surefire, you may notice that none of your tests is being triggered. This is due to the way tests is being discovered using the new version of Junit. In order to make Surefire work as intended, add the following two dependencies:
<!-- SUREFIRE -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.19.1</version>
<configuration>
<excludes>
<exclude>**/**/*IntTest.java</exclude>
<exclude>**/**/*CtxTest.java</exclude>
</excludes>
<includes>
<include>**/*Test.java</include>
</includes>
</configuration>
<dependencies>
<dependency>
<groupId>org.junit.platform</groupId>
<artifactId>junit-platform-surefire-provider</artifactId>
<version>${junit.platform.version}</version>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<version>${junit.helpers.version}</version>
</dependency>
</dependencies>
</plugin>
Make sure that you do not use the latest version of Surefire (In writing: 2.20.1), as there is some issue with the plugin itself. More about that stuff in the user-guide found on Junit5' own pages.
This is quite simple and is also described a bit on the various examples found on the github account related to Junit5: https://github.com/junit-team/junit5-samples.
This is a sample where surefire is used as the test-runner as a plugin.
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-params</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.platform</groupId>
<artifactId>junit-platform-launcher</artifactId>
<scope>test</scope>
</dependency>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.22.1</version>
<dependencies>
<!--OPTIONAL, if using junit4-->
<dependency>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
<version>5.3.1</version>
</dependency>
</dependencies>
</plugin>
Note: In case you're using an older version of surefire, you may need to include platform launcher and the following dependency for the plugin:
<dependency>
<groupId>org.junit.platform</groupId>
<artifactId>junit-platform-surefire-provider</artifactId>
<version>1.3.2</version>
</dependency>
You don't need the old junit:junit:4.()
version present in your project, this should be omitted/removed as dependency.
This is a summary of all changes that we had to make for one of our small applications:
Junit specifics
- Change org.junit.Test => org.junit.jupiter.api.Test
- Change org.junit.Assert => org.junit.jupiter.api.Assertions
- Change @Test(expected = VerifyException.class) => assertThrows(VerifyException.class, () -> WhateverClass.thatThrowsException());
- Change public class MyClassTest {} => class MyClasstest {}
- Change public void myAwsomeTestMethod() {} => void myAwsomeTestMethod() {}
- @Test(timeout = 10_000) => assertTimeout(Duration.ofMillis(TIMEOUT), () -> WhateverClass.thatTakesSomeTime());
Mockito specifics
- Change org.mockito.Matchers => org.mockito.ArgumentMatchers
- Some methods are marked as @Deprecated now, fix them accordingly as in Mockito 3.0.+ many of the marked classes/methods will be removed
- @RunWith(MockitoJUnitRunner.class) => Mocktio does not provide provider to @ExecuteWith yet, so you will have to use the following instead for now: @BeforeEach void setUp() {MockitoAnnotations.initMocks(this);}
Spring specifics
- @RunWith(SpringJUnit4ClassRunner.class) => @ExtendWith(SpringExtension.class)
Converting a rather small web-application with just around 5.9k lines of code (according to Sonar, atleast) - it took just about 1.5 hour of work to get everything working as intended. There were a few quirks along the line, however nothing that were unhandlable.