Parameterized Tests using JUnit5

Gurkan Demir
iyzico.engineering
Published in
5 min readOct 21, 2020

--

In this article, I am going to give you brief idea about Parameterized Tests using JUnit5. We will see how parameterized tests work and observe ways of providing different parameters to test methods.

As we all know, writing tests is one of the most important parts of software development cycle. Tests are very essential while developing even small tasks. Thanks to the tests, we can check whether our product works correctly, whether previously developed areas are affected, and whether different services interact with each other as desired. In short, tests indicate the quality of our code, and of our product. While we are developing in iyzico, we write tests which covers from the simplest to the most complex scenarios in order to observe that our code works as we want 🚀.

However, while testing, it is common to implement a series of tests which vary only by input values and expected results. For those specific instances, we could write separate tests for different scenarios but that may lead to code duplication 🤦‍♂.

So, let’s observe this situation in an example.

Below, we have a simple method named checkNumber which takes a single integer input as parameter and returns POSITIVE if it is greater than zero, NEGATIVE if it is less than zero, ZERO if it is equal to zero.

Simple demo class.

In order to cover all scenarios we have to test this method with at least 3 input parameters. In those test cases our input parameter must be positive, negative and zero, respectively.

Non-parameterized tests for demo method.

As we can see from the examples above, there are 3 different tests where only the input parameter differs. In other words, we call the same method with distinct variables. So, it seems like there exists redundant test code. This is where parameterized tests come in handy 😎.

The parameterized test uses different values to perform the same test over and over again. Using a parameterized test, we can perform the same test many times with different inputs. To do that, we add certain parameters to a test method and run it with different parameter value variations. This helps developers save time in carrying out the same test that differs only in their inputs and expected outcomes ✅.

Now, we know the basic concept of parameterized tests, so let’s take a deeper look at what we need to get started with JUnit5 parameterized tests.

To be able to write parameterized tests, first we need to add its dependencies to our project.

  • For maven,
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
<version>5.4.2</version>
<scope>test</scope>
</dependency>
  • For gradle,
testCompile("org.junit.jupiter:junit-jupiter-params:5.4.2")

Then, we need to alter the way we define our test methods. Previously, we were using @Test annotation, however in parameterized tests we use @ParameterizedTest annotation.

Finally, we need to provide arguments, which are input parameters that we want to execute our test method. There are various ways to declare arguments.

  • Value Source
  • Enum Source
  • CSV Source
  • CSV File Source
  • Method Source

So let’s analyze the most common ones.

Value Source

Value Source is the most basic type of argument source. It enables us to pass input parameters as an array of literal values to the test method.

To pass arguments, we have to use @ValueSource annotation. Below you can find examples for demo method.

Value Source parameterized tests for demo method.

However, there are some drawbacks of this kind of argument source:

  • It can only be used on test methods that have a single parameter.
  • It supports only following types of literal values: short, byte, int, long, float, double, char, java.lang.String, java.lang.Class
  • We can not pass null, or empty. For those cases we have to use @NullSource or @EmptySource.

CSV Source

Sometimes we need to implement test method that takes more than one input parameters. For such cases, Value Source is not enough.

CSV Source accepts an array of comma-separated values. Each time, this source takes one array entry, splits it by comma and passes each argument as separate parameters to the annotated test process. The comma is the column separator by default, but using the delimiter attribute, we can alter it.

Below you can find examples for demo method.

CSV Source parameterized tests for demo method.

We may pass certain values using a CSV file rather than obtaining the argument values within the code. We need to use @CsvFileSource annotation for such cases and pass the file name as input.

Method Source

The sources of arguments we have discussed so far are quite basic and have common drawback. It is difficult or impossible to use complex objects to pass them.

In addition to allowing us to pass many arguments, Method Source also provides us the ability to have more complicated arguments.

@MethodSource annotation accepts a method which is a static method that returns a Stream of Arguments. Arguments are consisting of as many parameters as you want, and elements of arguments can be type of any class.

Below you can find examples for demo method.

Method Source parameterized tests for demo method.

If we do not define the @MethodSource method name, JUnit searches for a source method with the same name as the test method.

I mostly prefer to use Method Source as argument source while writing parameterized tests.

Customizing Display Names

JUnit5 parameterized tests show names include the invocation index and the representation string of all parameters, by default. However, through the name attribute of the @ParameterizedTest annotation, we can customize the show name.

Default test display name.
Customized test display name.

Conclusion

To summarize, testing is an essential part of software development. With JUnit5, the parameter makes it easy to write tests. Thanks to the parameterized test, we will avoid duplicate codes and unnecessary lines.

I hope you have had enough knowledge about parameterized tests and have been able to understand how to write parameterized tests with JUnit5 🙏.

The example code for this article can be found on my personal Github 👋.

References

--

--