Quickly Transitioning to JUnit 5
A guide for moving from JUnit 4 to JUnit 5 in minutes
Any software development activity is not worth doing if testing isn’t part of the plan. With modern development practices, building small, simple applications is critical to keeping complexity down.
Frameworks, like JUnit, have emerged to support simplifying unit testing. JUnit uses a basic assert model to prove something works. In the assert model, there are methods to handle every type of case like true/false, null or not, equality, same, etc…
JUnit has been around for a very long time (it was first released in 2002), and it is one of the most-used unit test frameworks today. Therefore many applications have it in place to do their unit testing, but it may be based on the older version.
This may mean the project sticks with an older version. Staying on something old is usually not a good option over the long term. The goal of this, is to highlight what’s new and how you can quickly convert to the new version.
JUnit 5
JUnit 5 is a major new edition of the popular unit test framework. This is a major update for a few reasons. The biggest reason is it is now moving forward and only supports Java 8 and above. The backward portability of JUnit to older Java Runtime Environment(JRE) versions has been a major blocker for JUnit to take advantage of new language features.
The other area that has changed is the new package naming structure. Moving from org.junit, the new structure for the API is at org.junit.jupitor.api. This was done to allow JUnit to support different parts of the JUnit ecosystem and different versions of the framework.
The next area to change is the renaming of some core annotations to help make them more descriptive. The following are a few items that have changed that are usually the most commonly used.
- @Ignore -> @Disabled
- @BeforeClass -> @BeforeAll
- @AfterClass -> @AfterAll
- @Before -> @BeforeEach
- @After -> @AfterEach
There is a lot more to JUnit 5, but the goal is to focus on integrating JUnit 5 into a project that is built on an older version of JUnit.
Old Project
An old project of mine, is a Weather Archiver that I wrote to collect weather data for my area and record it every 15 minutes. This is a microservice built using Spring Boot, but it has a collection of JUnit 4 tests. The goal will be to take this service as is and integrate JUnit 5 into it. This will then show how it can be integrated with very little change to existing tests and can offer a path forward for leveraging JUnit 5 on future tests.
Updating the Dependency
The first step is to update the project to use JUnit 5 which is easy as changing a dependency in the Maven pom.xml.
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13</version>
<scope>test</scope>
</dependency>
Becomes
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<version>5.8.2</version>
<scope>test</scope>
</dependency>
Now lets build our project.
mvn clean package
That worked better then expected. Everything still builds (no API changes) and all the test continue to pass. At this point JUnit 5 is integrated into the project and we didn’t have to update anything but a dependency. JUnit is fully backward compliant in this case.
Change over an existing test
Since no changes were required, let’s begin by modifying an existing test to just get our feet wet with JUnit 5.
The old test for the controller’s convert method:
import static org.junit.Assert.assertNotNull;
import org.junit.Before;
import org.junit.Test;public class WeatherRetrieverTest { private WeatherRetriever retriever; @Before
public void setUp() throws Exception { retriever = new WeatherRetriever();
} @Test
public void testConvert() {
final OwmWeatherReport report = new OwmWeatherReport(); final WeatherReportEntity entity = retriever.convert(report); assertNotNull(entity);
}}
To update this, we’ll change the imports, update the @Before annotation and use the new API for assertNotNull.
import static org.junit.jupiter.api.Assertions.assertNotNull;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;public class WeatherRetrieverTest { private WeatherRetriever retriever; @BeforeEach
public void setUp() throws Exception { retriever = new WeatherRetriever();
} @Test
public void testConvert() {
final OwmWeatherReport report = new OwmWeatherReport(); final WeatherReportEntity entity = retriever.convert(report); assertNotNull(entity);
}
}
As demonstrated above, the imports changed to the new package name and the @Before annotation become @BeforeEach. No other changes were required to make this function under JUnit 5. That can’t be any easier.
Finally
As this illustrates, changing over to JUnit 5 can be as easy as updating a dependency. For any project, this should be the minimal step and should be as simple as shown unless more advanced features are leveraged.
After integrating JUnit 5, all new tests should be written using it. Typically it’s not worth converting older tests to JUnit 5 unless there is something that requires it. But switching to JUnit 5 should be done so that new features can be leveraged in the future.
If more information is required or you want to dig into the new features, JUnit publishes a very helpful guide with all the details necessary to start taking advantage of the improvements available.
I love receiving comments and suggestions and if you like this please remember to clap and follow me.