Spring Boot is a powerful framework for building Java applications with minimal configuration. WireMock is a library for stubbing and mocking web services for testing purposes. In this tutorial, we will integrate WireMock with Spring Boot to demonstrate how you can create and test RESTful services with ease.
Table of Contents
- Introduction to Spring Boot
- Introduction to WireMock
- Setting up a Spring Boot Project
- Integrating WireMock
- Creating a RESTful Service
- Testing with WireMock
- Conclusion
1. Introduction to Spring Boot
Spring Boot simplifies the process of building production-ready applications by providing a set of conventions and out-of-the-box functionality. It reduces boilerplate code and allows developers to focus on business logic.
2. Introduction to WireMock
WireMock is a flexible library for stubbing and mocking web services. It allows you to simulate HTTP responses from external services, making it ideal for testing when these services are unavailable or unreliable.
3. Setting up a Spring Boot Project
First, make sure you have Spring Boot installed. You can either use Spring Initializr (https://start.spring.io/) to generate a new project or add the Spring Boot dependencies to your existing project.
For this tutorial, we will create a simple Spring Boot project with Gradle.
Step 1: Create a new Spring Boot project
spring init --name spring-boot-wiremock --dependencies web,devtools spring-boot-wiremock
Step 2: Add WireMock Dependency
Add the WireMock dependency to your build.gradle
file:
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-web'
developmentOnly 'com.github.tomakehurst:wiremock-jre8:2.30.1'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
}
Step 3: Build and Run
Build and run your Spring Boot application:
./gradlew build
./gradlew bootRun
4. Integrating WireMock
In Spring Boot, you can integrate WireMock by creating a custom configuration.
Step 1: Create WireMock Configuration
Create a new Java class named WireMockConfig
:
import com.github.tomakehurst.wiremock.WireMockServer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class WireMockConfig {
@Bean(initMethod = "start", destroyMethod = "stop")
public WireMockServer wireMockServer() {
return new WireMockServer(8080);
}
}
Step 2: Start WireMock with Spring Boot
Modify your main application class to start WireMock along with your Spring Boot application:
import com.github.tomakehurst.wiremock.WireMockServer;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;
@SpringBootApplication
public class SpringBootWireMockApplication {
public static void main(String[] args) {
ConfigurableApplicationContext context = SpringApplication.run(SpringBootWireMockApplication.class, args);
WireMockServer wireMockServer = context.getBean(WireMockServer.class);
wireMockServer.start();
}
}
5. Creating a RESTful Service
Let’s create a simple RESTful service that retrieves user data.
Step 1: Create User Model
Create a simple User
model:
public class User {
private Long id;
private String name;
private int age;
// Getters and setters
}
Step 2: Create UserController
Create a REST controller to handle user requests:
import org.springframework.web.bind.annotation.*;
@RestController
@RequestMapping("/api/users")
public class UserController {
@GetMapping("/{id}")
public User getUser(@PathVariable Long id) {
// This would normally fetch data from a database
User user = new User();
user.setId(id);
user.setName("John Doe");
user.setAge(30);
return user;
}
}
6. Testing with WireMock
Now let’s write a test to use WireMock to mock an external API call.
Step 1: Write Integration Test
Create an integration test for UserController
:
import com.github.tomakehurst.wiremock.client.WireMock;
import com.github.tomakehurst.wiremock.junit.WireMockRule;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.web.servlet.MockMvc;
import static com.github.tomakehurst.wiremock.client.WireMock.*;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
@RunWith(SpringRunner.class)
@SpringBootTest
@AutoConfigureMockMvc
public class UserControllerIntegrationTest {
@Rule
public WireMockRule wireMockRule = new WireMockRule(8080);
@Autowired
private MockMvc mockMvc;
@Test
public void testGetUser() throws Exception {
stubFor(get(urlEqualTo("/api/users/1"))
.willReturn(aResponse()
.withHeader("Content-Type", "application/json")
.withBody("{\"id\": 1, \"name\": \"Mock User\", \"age\": 25}")));
mockMvc.perform(get("/api/users/1"))
.andExpect(status().isOk())
.andExpect(jsonPath("$.name").value("Mock User"))
.andExpect(jsonPath("$.age").value(25));
verify(getRequestedFor(urlEqualTo("/api/users/1")));
}
}
In this test:
- We’re using WireMock’s
WireMockRule
to create a server that listens on port 8080. - We stub a GET request to
/api/users/1
with a mocked response. - Then, we use
MockMvc
to perform a GET request to our Spring Boot service. - Finally, we verify that WireMock received a request to
/api/users/1
.
7. Conclusion
WireMock allows you to easily simulate external dependencies, making your tests more robust and independent. This approach ensures that your application behaves as expected, even when external services are not available.
Remember, WireMock is a powerful tool with many more features for more complex testing scenarios. Check out the WireMock documentation for more details and advanced usage.