First steps to using JUnit 5

Silas Candiolli
abbeal’s tech blog
4 min readMay 12, 2023
https://junit.org/junit5/

In my previous article on Unit Tests and Mockito, I discussed the advantage of using Mockito to manipulate object instances to focus on testing just what you want. That is awesome, you can use many combinations of returns and test all possibilities your method needs.

The latest versions of JUnit and Mockito brings some syntax and behavior changes. In this article, I want to explain how to start using JUnit 5 and hope to answer the following questions:

1. How can I update my project without changing all the tests simultaneously?

2. How can I use the new features?

First of all, I’m checking the release notes. It’s essential to do this because I can look directly into this library's primary source of knowledge, the documentation, what’s new, and what’s deprecated. Here I can find the Release Notes of JUnit 5.9.2

1. How can I update my project without changing all the tests simultaneously?

Let’s say I want to upgrade the JUnit, but I can’t change all tests within my project. I must adjust by taking baby steps because that takes some time and I can’t stop all my features and bug fixes just to adjust the tests.

Then I must add this Jupiter JUnit dependency:

<dependency>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
<version>${junit.jupiter.version}</version>
<scope>test</scope>
</dependency>

2. How can I use the new features?

Thinking in baby steps, I’m starting with syntax changes. For example, if I remove the junit-vintage-engine dependency, some errors will happen on my tests.

2.1. RunWith, Before, and Test annotations

Like the RunWith, Before, and Test annotations. Note that the first change is the packages path.

On JUnit 4 it was org.junit.*, now in JUnit 5 it is org.junit.jupiter.* .

To execute the test using Mockito, the annotation @RunWith(MockitoJUnitRunner.class)changes to @ExtendWith(MockitoExtension.class) .

When I need to execute code before each test, in JUnit 4 I use @Before, now on JUnit 5 I use @BeforeEach .

I also need to change the class that makes the assertions of my test. That class will compare the values and return a positive or negative value. Change from Assert.assertEquals to Assertions.asserEquals .

It is possible to compare the following two blocks.

JUnit 4

import org.junit.*;
import org.junit.runner.RunWith;

@RunWith(MockitoJUnitRunner.class)
class MyTest {

Customer myCustomer = null;
CustomerRegisterUseCase registerUseCase = null;

@Before
public void setUp() {
myCustomer = new Customer();
registerUseCase = new CustomerRegisterUseCase();
}

@Test
public void should_validade_customer_data() {
...
Assert.assertEquals(true, registerUseCase.register(myCustomer));
}
}

JUnit 5

import org.junit.jupiter.api.*;
import org.junit.jupiter.api.extension.ExtendWith;

@ExtendWith(MockitoExtension.class)
class MyTest {

Customer myCustomer = null;
CustomerRegisterUseCase registerUseCase = null;

@BeforeEach
public void setUp() {
myCustomer = new Customer();
registerUseCase = new CustomerRegisterUseCase();
}

@Test
public void should_validade_customer_data() {
...
Assertions.assertEquals(true, registerUseCase.register(myCustomer));
}
}

2.2. DisplayName

Ok, moving forward with new features of JUnit 5. Let’s say I want to have a better name for my test method, to identify it better when running the tests using an IDE. For that I may use @DisplayName:

@Test
@DisplayName("Should register a new customer with success")
public void register_success() throws InvalidValueException {
...
}

My test output should be the following:

2.3. ParameterizedTest

Since JUnit version 5.7 we can take advantage of the facilities of the Parameterized Tests. And why not save time and lines of code using this feature?

A parametrized test is a manner to run a test several times with different values.

According to the documentation:

@ParameterizedTest is used to signal that the annotated method is a parameterized test method.

And it works in conjunction with another annotation:

@ParameterizedTest methods must specify at least one ArgumentsProvider via @ArgumentsSource or a corresponding composed annotation (e.g., @ValueSource, @CsvSource, etc.). The provider is responsible for providing a Stream of Arguments that will be used to invoke the parameterized test method.

So, basically, we mark in the test method that it will receive parameters to execute, and these parameters will come from other annotations, such as @ValueSourceor @CsvSource .

To start using the @ParameterizedTest you should first add the following dependency:

<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-params</artifactId>
<version>${junit.jupiter.version}</version>
<scope>test</scope>
</dependency>

Considering the class CustomerRegister , where there is the use case method to register a new Customer, and another method to validate if the Customer CPF is real.

The junit-jupiter-param library brings us some options for using parameterized tests, which are:

ValueSource

CsvSource

CsvFileSource

To use this feature, I should create a csv file to store my tests cases, something like that:

And my test should be something like that:

Conclusion

These are some of the new features you can use, exists more than that, but I hope that would be the first step for you to start using JUnit 5.

Keeping your JUnit up to date will speed up the creation of your tests, and also maintain compatibility with the latest versions of Java.

I hope you’ve learned something, but don’t stop there. Go ahead, create more tests, and increase the quality of your software.

--

--