JUnit 4: Parameterized Implementation for Integration Test

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 Caspar Camille Rubin on Unsplash

In the previous article, I have written how parameterized in JUnit4 works. In this article, I will show how to create an integration test helper using parameterized from JUnit 4. I’ll provide an example by creating a Spring Boot project with the required dependencies:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.3.0.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.nantaaditya</groupId>
<artifactId>parameterized</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>parameterized</name>
<description>Demo project for parameterized junit4</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.rest-assured</groupId>
<artifactId>rest-assured</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.github.tomakehurst</groupId>
<artifactId>wiremock-standalone</artifactId>
<version>2.5.1</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>

In the next step, I will create a simple CRUD API, where the API has several functions for creating, reading, updating, and deleting data. I’ll skip this step, but for those of you who want to see the code please check out my Github.

After the code for API is complete, we will create a helper class. For a simpler explanation of this helper, please see the class diagram below.

parameterized helper diagram class

Brief Explanation:

  • BeforeTest and AfterTest, these functional interfaces are used to run lines of code before or after a test case is run.
  • ResultAssertion: will be used to assert the API response that being tested.
  • TestSpecification, this class will be used to input test cases.
  • BaseIntegrationTest is a helper to run the integration test. The class that will use this helper must override the abstract method setUp and tearDown to do something before or after a test case is run.
  • Then the last thing is to use the helper we’ve made earlier in a controller test class, wherein this class we have to do the following steps:

→ provides the following annotations at the controller test class level.

@RunWith(Parameterized.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT)
@TestPropertySource(locations = "classpath:application.properties")

→ then we create 2 variables to run the integration test.

@ClassRule
public static final SpringClassRule SPRING_CLASS_RULE
= new SpringClassRule();

@Rule
public final SpringMethodRule springMethodRule
= new SpringMethodRule();

→ Create a constructor for the controller test class with the parameter TestSpecification class, where we’ll perform test case injection using this constructor. In this constructor, we’ll call the constructor of its parent class.

→ Then override the setUp and tearDown methods. if we want to do something before or after a test case is run.

→ The last, we create a function with a return value Collection<TestSpecification>. We’ll input the test case that we want to execute in this function, and also don’t forget to add an annotation to the function with @Parameterized.Parameters.

→ make sure we create a test property according to the port that we’ve defined in the BaseIntegrationTest class, we’ll adjust the rest according to our needs. Suppose we need a database to perform an integration test, we can add these to the test property.

server.port=18181

Wholaaa this is the complete code. When the above code is executed, it’ll produce the output like below.

integration test result

By creating a helper, we don’t need to re-setup for other integration tests, just reuse the helper we’ve created earlier.

Too Ez right? Using that way we can reduce the duplication of the test code to initiate the integration test. ‘cause we only need to create the test case scenario. And in my personal opinion, the test scenarios are easier to read.
If there are any suggestions or questions, please leave a comment below. ❤

--

--