Crux Intelligence
Published in

Crux Intelligence

Testing Spring Boot Application using WireMock and JUnit 5

Spring Boot with WireMock

What is WireMock?

WireMock Flow

Why do we need WireMock?

What is JUnit 5?

Steps to Build

  1. Set up the Spring Boot Project
  2. Include Additional Maven Dependencies
  3. Furnish the Configurations
  4. Define a DTO Class
  5. Define the Rest Controller Endpoints
  6. Construct the Service Layer
  7. Start the Application
  8. Test the Application with Swagger-UI
  9. Add Integration Test
  10. Conclusion

1. Set up the Spring Boot Project

  • Spring Web: Build web, including RESTful, applications using Spring MVC. Uses Apache Tomcat as the default embedded container.
Creating Sample Project

2. Include Additional Maven Dependencies

<dependency>
<groupId>org.springdoc</groupId>
<artifactId>springdoc-openapi-ui</artifactId>
<version>1.6.9</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.24</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.github.tomakehurst</groupId>
<artifactId>wiremock-standalone</artifactId>
<version>2.27.2</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<version>5.8.2</version>
<scope>test</scope>
</dependency>

3. Furnish the Configurations

@Configuration
public class ApplicationConfig {
@Bean
public RestTemplate restTemplate(RestTemplateBuilder builder) {
// Do any additional configuration here
return builder.build();
}
}
spring:
application:
name: "Sample Spring Boot Application"

universitiesBaseURL: http://universities.hipolabs.com
@Configuration
@ConfigurationProperties(prefix = "wiremock-config")
@Data
@Profile("integration")
public class WireMockConfig {
private List<WireMockProxy> proxies;
}

4. Define a DTO Class

@Data
@JsonIgnoreProperties(ignoreUnknown = true)
@JsonInclude(JsonInclude.Include.NON_NULL)
public class UniversityDTO {
private List<String> domains;
private List<String> web_pages;
private String name;
private String country;
private String alpha_two_code;
}

5. Define the Rest Controller Endpoints

UniversityController

6. Construct the Service Layer

UniversityService

7. Start the Application

mvn clean package
Starting the application

8. Test the Application with Swagger-UI

http://localhost:8080/swagger-ui/index.html
Swagger-UI
Sample Test using Swagger

9. Add Integration Test

application-integration.yml
Integration configurations
test directories
  • __file (contains response errors and messages JSON)
  • mappings (contains request and response JSON) directories that are needed by WireMock for recording purposes
  • recorded directory is used to capture the actual response of the REST API which we will use to compare against our Integration test results
Integration Test file
SpringBootWiremockApplicationTests
  • Set the active profile: In line 1 we are directing our tests to use the profile: integration by annotating the test class with the @ActiveProfiles annotation. By setting integration profile as the active profile, the tests will read the configurations from the file application-integration.yml which we defined in step 9.1.
  • Look up main configuration class: In line 2 @SpringBootTest annotation tells Spring Boot to look for the main configuration class (one with @SpringBootApplication, for instance) and use that to start a Spring application context.
  • Configure auto-configuration of MockMVC: We also have added the annotation @AutoConfigureMockMvc in line 4 because we’ll use MockMvc to call the “/api/university “ endpoint for the test. We could have called the service method directly depending on what kind of test we wanted to implement. In this article, we are trying to demonstrate an example of an integration test by calling the REST endpoints directly with MockMvc.
  • Start WireMock server and record: From line 24 to 36 we defined a method called startRecording, which will be executed before every test case. It reads the configuration file defined in step 9.1. If recording flag is turned on then it will start the WireMock server in recording mode, else it will start in regular mode.
  • Shut down WireMock server and stop recording: From line 39 to 48 we defined a method called stopRecording which will be executed after every test case. If recording flag is turned on then it will stop the recording before shutting down the WireMock server in recording mode or else it will just stop the server in regular mode.
  • Provide WireMock server configuration: From line 124 to 133 we have provided some configuration for the WireMock server. It will start intercepting all the requests specified at the wiremock-config.proxies.url. In this tutorial we have specified only one URL : http://universities.hipolabs.com. If the recording is enabled then it will persist the stubs in the mappings folder. While matching against the stubs it will ignore the arrayOrder and extraElements in the response JSON.
  • Define integration test case: From line 51 to 63 we defined the integration test case for the REST API “/api/university”. Here we have used the parameterized test case of JUnit 5. MockMvc is used to call the “/api/university “ endpoint. It then saves the response temporarily in JSON format to compare against the expected response. Here, we are using JsonAssert to compare the expected and actual JSON responses. Once the test case is successful then the current file is cleaned up automatically.

9.4 Record the Test Case

recording enabled
recording the test case
running test case in recording mode
recorded files captured

9.5 Replay the Test Case

recording disabled
replay the test case
Running the test case with recording off
update the captured response
no recording found

Conclusion

References & Useful Readings

--

--

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store