Simulate Slow Responses in a Spring Boot Application

Bubu Tripathy
4 min readMar 22, 2023

--

In this blog post we will see how to use WireMock to simulate slow responses for a Spring Boot application. WireMock is a powerful tool that allows you to simulate HTTP responses. One of the features of WireMock is the ability to simulate slow responses. This can be useful in testing scenarios where you want to test how your application handles slow responses from a remote server.

Setting up the environment

Before we can start using WireMock, we need to set up our development environment. We will be using Spring Boot 2.5.4, Java 11, and Maven 3.8.3.

First, we need to add the WireMock dependency to our Maven project. We can do this by adding the following dependency to our pom.xml file:

<dependency>
<groupId>com.github.tomakehurst</groupId>
<artifactId>wiremock</artifactId>
<version>2.27.2</version>
</dependency>

Next, we need to create a new Java class to set up the WireMock server. We can call this class WireMockConfig:

import com.github.tomakehurst.wiremock.WireMockServer;
import com.github.tomakehurst.wiremock.client.WireMock;

import static com.github.tomakehurst.wiremock.client.WireMock.*;

public class WireMockConfig {

private WireMockServer wireMockServer;

public void start() {
wireMockServer = new WireMockServer(options().port(8080));
wireMockServer.start();
configureFor("localhost", 8080);
}

public void stop() {
wireMockServer.stop();
}

public void reset() {
WireMock.reset();
}

public void stubSlowResponse() {
stubFor(get(urlEqualTo("/slow-response"))
.willReturn(aResponse()
.withFixedDelay(5000)
.withStatus(200)));
}

}

In this class, we create a new instance of the WireMock server and configure it to listen on port 8080. We also define a method to stub a slow response. This method sets up a WireMock stub for a GET request to the /slow-response endpoint that returns a response with a fixed delay of 5 seconds and a status code of 200.

Testing the Spring Boot application

Now that we have set up our WireMock server, we can use it to test our Spring Boot application. In this example, we will create a simple REST controller that makes an HTTP request to the /slow-response endpoint and returns the response body.

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

@RestController
public class SlowResponseController {

@GetMapping("/slow-response")
public String getSlowResponse() {
RestTemplate restTemplate = new RestTemplate();
String response = restTemplate.getForObject("http://localhost:8080/slow-response", String.class);
return response;
}
}

To test our controller, we can create a new JUnit test class and use the WireMockConfig class to set up our WireMock server:

import com.github.tomakehurst.wiremock.junit.WireMockRule;
import org.junit.Before;
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.WebMvcTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import org.springframework.test.web.servlet.result.MockMvcResultMatchers;

import static com.github.tomakehurst.wiremock.client.WireMock.*;

@RunWith(SpringRunner.class)
@WebMvcTest(SlowResponseController.class)
public class SlowResponseControllerTest {
@Autowired
private MockMvc mockMvc;

@MockBean
private RestTemplate restTemplate;

@Rule
public WireMockRule wireMockRule = new WireMockRule(8080);

@Autowired
private WireMockConfig wireMockConfig;

@Before
public void setup() {
wireMockConfig.start();
}

@Test
public void should_return_slow_response() throws Exception {
wireMockConfig.stubSlowResponse();

mockMvc.perform(MockMvcRequestBuilders.get("/slow-response"))
.andExpect(MockMvcResultMatchers.status().isOk());

verify(getRequestedFor(urlEqualTo("/slow-response")));
}
}

In this test class, we use the WireMockRule to start our WireMock server on port 8080. We also use the WireMockConfig class to stub a slow response for the /slow-response endpoint. Finally, we use the MockMvc class to perform an HTTP GET request to our controller and verify that the response status code is 200.

Simulating a slow response with a dynamic delay

In the previous example, we used the withFixedDelay method to simulate a fixed delay of 5 seconds. However, in real-world scenarios, the response time of an external service can vary depending on various factors such as network conditions, server load, etc. In such cases, it can be more realistic to simulate a dynamic delay.

To simulate a dynamic delay, we can use the withUniformRandomDelay method instead of withFixedDelay. This method takes two arguments - the minimum and maximum delay time in milliseconds - and generates a random delay between these two values for each response. Here's an example of how to use it:

public void stubDynamicDelayResponse() {
stubFor(get(urlEqualTo("/dynamic-delay-response"))
.willReturn(aResponse()
.withUniformRandomDelay(1000, 5000)
.withStatus(200)));
}

In this example, we are simulating a delay between 1 and 5 seconds for each response.

Simulating a slow response with a delay distribution

In some cases, the response time of an external service might follow a specific distribution, such as a normal distribution or a Poisson distribution. To simulate such scenarios, we can use the withLogNormalDistribution or withPoissonDistribution method instead of withFixedDelay. Here’s an example of how to use withLogNormalDistribution to simulate a response time with a log-normal distribution:

public void stubLogNormalDelayResponse() {
stubFor(get(urlEqualTo("/log-normal-delay-response"))
.willReturn(aResponse()
.withLogNormalDistribution(5000, 1.0)
.withStatus(200)));
}

In this example, we are simulating a response time with a log-normal distribution, where the mean delay is 5 seconds and the standard deviation is 1.0. By using different distribution methods, we can simulate a wide range of response time scenarios and test how our application handles them.

Simulating a slow response with a delay sequence

In some cases, we might want to simulate a sequence of responses with increasing delay times, such as when testing how our application handles timeouts. To simulate such scenarios, we can use the withDelaySequence method instead of withFixedDelay. Here’s an example of how to use withDelaySequence to simulate a sequence of responses with increasing delay times:

public void stubDelaySequenceResponse() {
stubFor(get(urlEqualTo("/delay-sequence-response"))
.willReturn(aResponse()
.withDelaySequence(1000, 2000, 3000, 4000, 5000)
.withStatus(200)));
}

In this example, we are simulating a sequence of responses with delay times of 1, 2, 3, 4, and 5 seconds. By using a delay sequence, we can test how our application handles different timeout scenarios and ensure that it gracefully handles such situations.

Conclusion

In this blog post, we have explored how to use WireMock to simulate slow responses for a Spring Boot application. By using the various delay methods provided by WireMock, we can simulate different response time scenarios and test how our application handles them.

Thanks for your attention! Happy Learning!

--

--