JUnit 4: Reducing Test Code Duplication using Parameterized

Pramuditya Ananta Nur
Blibli.com Tech Blog
3 min readJun 2, 2021

Before you continue reading this article, I assume that you know the basics of Spring Boot and JUnit.

Photo by Christopher Gower on Unsplash

Unit test is one of the white box tests to validate whether the component’s functionality in the application that we’ve created meets the requirements. As a developer who works at blibli.com, Sometimes I encounter problems in making unit tests, for example finding a lot of unit test code duplication at the controller layer. Where most unit tests have been written, only cover one test case. And when I want to cover several test cases, of course, there will be more code duplication and it’s quite time-consuming in the development phase.

One of the unit test frameworks used at blibli.com is JUnit. After reading through JUnit documentation, this framework has provided the functionality to run multiple tests using different values for each test case, it’s called Parameterized. So, I tried to implement this feature to solve the problem I’ve mentioned above.

How does the parameterized work?

Before explaining further how I implemented Parameterized as a solution, I’ll give you an example and explain how parameterized works in the simplest way. Please look at the following line of code below:

import java.util.Arrays;
import java.util.Collection;

import org.junit.Test;
import org.junit.Before;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameters;
import org.junit.runner.RunWith;
import static org.junit.Assert.assertEquals;
// 1
@RunWith(Parameterized.class)
public class OddCheckerTest {
// 2
private Integer inputNumber;
private Boolean expectedResult;

// 3
public OddCheckerTest(
Integer inputNumber, Boolean expectedResult) {
this.inputNumber = inputNumber;
this.expectedResult = expectedResult;
}
// 4
@Parameterized.Parameters(name="Test - {0} is odd number: {1}")
public static Collection numbers() {
return Arrays.asList(new Object[][] {
{ 1, true },
{ 6, false },
{ 19, true },
{ 22, false },
{ 23, true }
});
}
// 5
@Test
public void testOddNumberChecker() {
System.out.println("Parameterized Number is: " + inputNumber);
assertEquals(expectedResult, inputNumber % 2 == 1);
}
}

Code Result

parameterized result

Code Explanation

Please pay attention to the code snippet with a comment mark (//).

  1. One of the conditions for running parameterized is to provide an annotation at the class level with @RunWith(Parameterized.class).
  2. Next, create parameters that the value will change according to the value of the test case. The value of these parameters will be injected via the constructor.
  3. Next, we must create a constructor that accepts the parameters we’ve created.
  4. In this step, we create a test case by creating a function that returns the static collection. Then we must annotate the function with @Parameterized.Parameters.
    The value in the annotation will be displayed on the IDE console, and also the values ​​of {0} and {1} will be replaced according to the order of the constructor parameter that we’ve created.
    In the test case, let’s say that there are rows and columns, where 1 row represents the value to be injected into the constructor and which will be executed as a test case, while the column is one of the parameters in the constructor. For example in the first line, the value of inputNumber is 1, and the value of expectedResult is true.
  5. Finally, we create a test method, wherein this method we run each test case and make an assertion for each test case. For each class, we only need one method with @Test annotation.

Conclusion

By knowing how to use Parameterized in making unit tests, we can make it as a helper to reduce code duplication and increase code coverage by making several test cases. It has impacts of minimizing bugs, less code to maintain, and also can reduce the time spent during the development phase. This feature has been implemented in my team to test the controller layer and also used for integration tests.

Regarding the use of Parameterized as a helper will be explained in the next article. See ya.

References:

https://github.com/junit-team/junit4/wiki/Parameterized-tests

--

--