This blog post describes how we can stub HTTP requests with WireMock. After we have finished this blog post, we:
- Know what stubbing is.
- Can configure the returned HTTP status code.
- Know how we can configure the returned HTTP headers.
- Understand how we can configure the body of the returned HTTP response.
- Can redirect HTTP requests to another location.
Let's begin.
- You are familiar with JUnit 5
- You are familiar with WireMock
- You can configure WireMock from the scratch
- You can specify expectations for the HTTP request method and request URL
- You can specify expectations for cookies, HTTP headers, and request parameters
- You can specify expectations for JSON documents received by your WireMock server
- You can specify expectations for XML documents received by your WireMock server
What Is Stubbing?
Stubbing is a technique that allows us to configure the HTTP response that is returned by our WireMock server when it receives a specific HTTP request. We can stub HTTP requests with WireMock by using the static givenThat()
method of the WireMock
class. When we invoke this method, we have to create a new MappingBuilder
object and pass this object to the invoked method as a method parameter. The MappingBuilder
object has two responsibilities:
- It identifies the HTTP request that triggers the configured HTTP response. We can identify the HTTP request by using WireMock's request matching support.
- It configures the returned HTTP response. We can configure the returned HTTP response by using the
willReturn()
method of theMappingBuilder
interface. When we invoke this method, we have to create a newResponseDefinitionBuilder
object and pass this object to the invoked method as a method parameter.
stubFor()
method of the WireMock
class. I use the givenThat()
method mainly because I like its name, but it's good to know that these two methods are interchangeable.For example, if we want to configure the HTTP response that is returned when our WireMock server receives a GET
request to the URL: '/api/message', we have to write a test method that looks as follows:
import com.github.tomakehurst.wiremock.WireMockServer; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.client.RestTemplate; import static com.github.tomakehurst.wiremock.client.WireMock.get; import static com.github.tomakehurst.wiremock.client.WireMock.givenThat; import static com.github.tomakehurst.wiremock.client.WireMock.urlEqualTo; import static org.assertj.core.api.Assertions.assertThat; @DisplayName("Configure the returned HTTP response") class StubbingTest { private RestTemplate restTemplate; private WireMockServer wireMockServer; @Test @DisplayName("Should return the configured HTTP response") void shouldReturnConfiguredHttpResponse() { //Identify the HTTP request givenThat(get(urlEqualTo("/api/message")).willReturn( //Configure the returned HTTP response )); String serverUrl = buildApiMethodUrl(); ResponseEntity<String> response = restTemplate.getForEntity(serverUrl, String.class ); //Write assertions for the returned response } private String buildApiMethodUrl() { return String.format("http://localhost:%d/api/message", this.wireMockServer.port() ); } }
- I removed the
@BeforeEach
and@AfterEach
methods from the code examples of this blog post because they add no value to this blog post. If you don't know how you can configure WireMock, you should read this blog post. - All examples of this blog post ensure that our WireMock server returns the configured HTTP response when it receives a
GET
request to the URL: '/api/message'.
Next, we will take a look at some examples that demonstrate how we can configure the returned HTTP response. Let's start by configuring the returned HTTP status code.
Configuring the Returned HTTP Status Code
If we want to configure the returned HTTP status code, we have to use one of these two options:
First, we can configure the returned HTTP status code by following these steps:
- Create a new
ResponseDefinitionBuilder
object by invoking thestatic aResponse()
method of theWireMock
class. - Configure the returned HTTP status code by using the
withStatus()
method of theResponseDefinitionBuilder
class.
For example, if we want to ensure that our WireMock server returns the HTTP status code 200, we have to write a test method that looks as follows:
import com.github.tomakehurst.wiremock.WireMockServer; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.client.RestTemplate; import static com.github.tomakehurst.wiremock.client.WireMock.*; import static org.assertj.core.api.Assertions.assertThat; @DisplayName("Configure the returned HTTP status code") class StubbingTest { private RestTemplate restTemplate; private WireMockServer wireMockServer; @Test @DisplayName("Should return the HTTP status code OK") void shouldReturnHttpStatusCodeOk() { givenThat(get(urlEqualTo("/api/message")).willReturn(aResponse() .withStatus(200) )); String serverUrl = buildApiMethodUrl(); ResponseEntity<String> response = restTemplate.getForEntity(serverUrl, String.class ); assertThat(response.getStatusCode()).isEqualTo(HttpStatus.OK); } private String buildApiMethodUrl() { return String.format("http://localhost:%d/api/message", this.wireMockServer.port() ); } }
Second, we can create the required ResponseDefinitionBuilder
object by using the static
factory methods of the WireMock
class. If we want to use this approach, we can use these factory methods: badRequest()
, badRequestEntity()
, created()
, forbidden()
, noContent()
, notFound()
, ok()
, serverError()
, serviceUnavailable()
, and unauthorized()
.
For example, if we want to ensure that our WireMock server returns the HTTP status code 200, we have to write a test method that looks as follows:
import com.github.tomakehurst.wiremock.WireMockServer; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.client.RestTemplate; import static com.github.tomakehurst.wiremock.client.WireMock.*; import static org.assertj.core.api.Assertions.assertThat; @DisplayName("Configure the returned HTTP status code") class StubbingTest { private RestTemplate restTemplate; private WireMockServer wireMockServer; @Test @DisplayName("Should return the HTTP status code OK") void shouldReturnHttpStatusCodeOk() { givenThat(get(urlEqualTo("/api/message")).willReturn(ok())); String serverUrl = buildApiMethodUrl(); ResponseEntity<String> response = restTemplate.getForEntity(serverUrl, String.class ); assertThat(response.getStatusCode()).isEqualTo(HttpStatus.OK); } private String buildApiMethodUrl() { return String.format("http://localhost:%d/api/message", this.wireMockServer.port() ); } }
- If we want to set only the HTTP status code of the returned HTTP response and the returned status code is supported by the
WireMock
class, we should create the requiredResponseDefinitionBuilder
object by using thestatic
factory methods of theWireMock
class. I think that this is a good choice because these factory methods allow us to configure the returned HTTP response without writing any boilerplate code. Also, because these methods are named properly, it's quite easy to see what the returned HTTP status code is. - If we want to configure the other properties of the returned HTTP response, we should create the required
ResponseDefinitionBuilder
object by using the manual approach. I think that this is a good choice because the manual approach emphasizes the properties of the returned HTTP response.
It's also possible to customize the status message of the returned HTTP response. We can do this by using the withStatusMessage()
method of the ResponseDefinitionBuilder
class. For example, if we want to ensure that our WireMock server returns the HTTP status code 500 and the status message: 'I am sorry', we have to write a test method that looks as follows:
import com.github.tomakehurst.wiremock.WireMockServer; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.client.HttpServerErrorException; import org.springframework.web.client.RestTemplate; import static com.github.tomakehurst.wiremock.client.WireMock.*; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.catchThrowable; @DisplayName("Configure the returned HTTP status code") class StubbingTest { private RestTemplate restTemplate; private WireMockServer wireMockServer; @Test @DisplayName("Should return the HTTP status code 500 and the correct message") void shouldReturnHttpStatusCodeOk() { givenThat(get(urlEqualTo("/api/message")).willReturn(aResponse() .withStatus(500) .withStatusMessage("I am sorry") )); String serverUrl = buildApiMethodUrl(); Throwable thrown = catchThrowable(() -> restTemplate.getForEntity(serverUrl, String.class )); assertThat(thrown) .isExactlyInstanceOf(HttpServerErrorException.class) .hasMessage("500 I am sorry"); } private String buildApiMethodUrl() { return String.format("http://localhost:%d/api/message", this.wireMockServer.port() ); } }
Next, we will learn to configure the returned HTTP headers.
Configuring the Returned HTTP Headers
If we want to configure the returned HTTP header, we have to use the withHeader()
method of the ResponseDefinitionBuilder
class. This method takes two method parameters:
- The name of the header.
- The header value.
For example, if we want to ensure that our WireMock server returns an HTTP header called: Name
, we have to write a test method that looks as follows:
import com.github.tomakehurst.wiremock.WireMockServer; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.client.RestTemplate; import static com.github.tomakehurst.wiremock.client.WireMock.*; import static org.assertj.core.api.Assertions.assertThat; @DisplayName("Configure the returned HTTP status code") class StubbingTest { private RestTemplate restTemplate; private WireMockServer wireMockServer; @Test @DisplayName("Should return the configured HTTP header") void shouldReturnConfiguredHttpHeader() { givenThat(get(urlEqualTo("/api/message")).willReturn(aResponse() .withStatus(200) .withHeader("Name", "Petri Kainulainen") )); String serverUrl = buildApiMethodUrl(); ResponseEntity<String> response = restTemplate.getForEntity(serverUrl, String.class ); assertThat(response.getStatusCode()).isEqualTo(HttpStatus.OK); assertThat(response.getHeaders().get("Name").get(0)) .isEqualTo("Petri Kainulainen"); } private String buildApiMethodUrl() { return String.format("http://localhost:%d/api/message", this.wireMockServer.port() ); } }
If we want to return multiple HTTP headers, we can either invoke the withHeader()
method multiple times or we can configure all returned headers at the same time.
If we want to configure all returned HTTP headers at the same time, we have to use the withHeaders()
method of the ResponseDefinitionBuilder
class. We can use this method by following these steps:
- Specify the returned HTTP headers by creating a new
HttpHeaders
object. - Invoke the
withHeaders()
method and pass the createdHttpHeaders
object as a method parameter.
For example, if we want to ensure that our WireMock server returns the HTTP headers called: Name
and Occupation
, we have to write a test method that looks as follows:
import com.github.tomakehurst.wiremock.WireMockServer; import com.github.tomakehurst.wiremock.http.HttpHeader; import com.github.tomakehurst.wiremock.http.HttpHeaders; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.client.RestTemplate; import static com.github.tomakehurst.wiremock.client.WireMock.*; import static org.assertj.core.api.Assertions.assertThat; @DisplayName("Configure the returned HTTP status code") class StubbingTest { private RestTemplate restTemplate; private WireMockServer wireMockServer; @Test @DisplayName("Should return the configured HTTP headers") void shouldReturnConfiguredHttpHeaders() { HttpHeaders headers = new HttpHeaders( new HttpHeader("Name", "Petri Kainulainen"), new HttpHeader("Occupation", "Software Developer") ); givenThat(get(urlEqualTo("/api/message")).willReturn(aResponse() .withStatus(200) .withHeaders(headers) )); String serverUrl = buildApiMethodUrl(); ResponseEntity<String> response = restTemplate.getForEntity(serverUrl, String.class ); assertThat(response.getStatusCode()).isEqualTo(HttpStatus.OK); assertThat(response.getHeaders().get("Name").get(0)) .isEqualTo("Petri Kainulainen"); assertThat(response.getHeaders().get("Occupation").get(0)) .isEqualTo("Software Developer"); } private String buildApiMethodUrl() { return String.format("http://localhost:%d/api/message", this.wireMockServer.port() ); } }
withHeader()
method multiple times because this approach allows us to configure the returned HTTP headers without writing any boilerplate code.Let's move on and find out how we can configure the body of the returned HTTP response.
Configuring the Body of the Returned HTTP Response
If we want to configure the body of the returned HTTP response, we have to also set its content type. We can configure the body of the returned HTTP response by using one of these three options:
First, we can configure the body of the returned HTTP response by following these steps:
- Create a new
ResponseDefinitionBuilder
object by invoking thestatic aResponse()
method of theWireMock
class. - Configure the content type of the returned HTTP response. We can do this by setting the value of the
Content-Type
header. - Configure the body of the returned HTTP response by using the
withBody()
method of theResponseDefinitionBuilder
class.
For example, if we want to ensure that our WireMock server returns a JSON document and sets the content type of the returned HTTP response to application/json;charset=UTF-8
, we have to write a test method that looks as follows:
import com.github.tomakehurst.wiremock.WireMockServer; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; import org.springframework.web.client.RestTemplate; import static com.github.tomakehurst.wiremock.client.WireMock.*; import static org.assertj.core.api.Assertions.assertThat; @DisplayName("Configure the returned HTTP status code") class StubbingTest { private RestTemplate restTemplate; private WireMockServer wireMockServer; @Test @DisplayName("Should return the configured HTTP response") void shouldReturnHttpConfiguredHttpResponse() { givenThat(get(urlEqualTo("/api/message")).willReturn(aResponse() .withStatus(200) .withHeader("Content-Type", "application/json;charset=UTF-8") .withBody("{ \"message\": \"Hello World!\" }") )); String serverUrl = buildApiMethodUrl(); ResponseEntity<String> response = restTemplate.getForEntity(serverUrl, String.class ); assertThat(response.getStatusCode()).isEqualTo(HttpStatus.OK); assertThat(response.getHeaders().getContentType()) .isEqualTo(MediaType.APPLICATION_JSON_UTF8); assertThat(response.getBody()) .isEqualTo("{ \"message\": \"Hello World!\" }"); } private String buildApiMethodUrl() { return String.format("http://localhost:%d/api/message", this.wireMockServer.port() ); } }
Second, we can read the body of the returned HTTP response from a file. If we want to use this approach, we have to follow these steps:
- Create the src/test/resources/__files directory.
- Create the file that contains the body of the HTTP response and put this file to the __files directory. Note that we can separate different body files by using subdirectories.
- Configure the location of the body file by using the
withBodyFile()
method of theResponseDefinitionBuilder
class. When we invoke this method, we have to pass the file path of our body file as a method parameter. Note that our file path must be a relative path that starts from the __files directory.
For example, if we want to ensure that our WireMock server reads the body of the returned JSON document from the path: src/test/resources/__files/json/hello.json, we have to write a test method that looks as follows:
import com.github.tomakehurst.wiremock.WireMockServer; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; import org.springframework.web.client.RestTemplate; import static com.github.tomakehurst.wiremock.client.WireMock.*; import static org.assertj.core.api.Assertions.assertThat; @DisplayName("Configure the returned HTTP status code") class StubbingTest { private RestTemplate restTemplate; private WireMockServer wireMockServer; @Test @DisplayName("Should return the configured HTTP response") void shouldReturnHttpConfiguredHttpResponse() { givenThat(get(urlEqualTo("/api/message")).willReturn(aResponse() .withStatus(200) .withHeader("Content-Type", "application/json;charset=UTF-8") .withBodyFile("json/hello.json") )); String serverUrl = buildApiMethodUrl(); ResponseEntity<String> response = restTemplate.getForEntity(serverUrl, String.class ); assertThat(response.getStatusCode()).isEqualTo(HttpStatus.OK); assertThat(response.getHeaders().getContentType()) .isEqualTo(MediaType.APPLICATION_JSON_UTF8); assertThat(response.getBody()) .isEqualTo("{ \"message\": \"Hello World!\" }"); } private String buildApiMethodUrl() { return String.format("http://localhost:%d/api/message", this.wireMockServer.port() ); } }
Third, we can configure the HTTP status code, content type, and body of the returned HTTP response by using the static
factory methods of the WireMock
class. We can use one of these three methods:
- The
okJson(String json)
method returns the HTTP status code 200, sets the content type of the HTTP response toapplication/json
, and returns the JSON document given as a method parameter. - The
okXml(String xml)
method returns the HTTP status code 200, sets the content type of the HTTP response toapplication/xml
, and returns the XML document given as a method parameter. - The
textXml(String xml)
method returns the HTTP status code 200, sets the content type of the HTTP response totext/xml
, and returns the XML document given as a method parameter.
For example, if we want to ensure that our WireMock server returns the HTTP status 200 and a JSON document, we have to write a test method that looks as follows:
import com.github.tomakehurst.wiremock.WireMockServer; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; import org.springframework.web.client.RestTemplate; import static com.github.tomakehurst.wiremock.client.WireMock.*; import static org.assertj.core.api.Assertions.assertThat; @DisplayName("Configure the returned HTTP status code") class StubbingTest { private RestTemplate restTemplate; private WireMockServer wireMockServer; @Test @DisplayName("Should return OK response for JSON") void shouldReturnOkResponseForJson() { givenThat(get(urlEqualTo("/api/message")).willReturn( okJson("{ \"message\": \"Hello World!\" }") )); String serverUrl = buildApiMethodUrl(); ResponseEntity<String> response = restTemplate.getForEntity(serverUrl, String.class ); assertThat(response.getStatusCode()).isEqualTo(HttpStatus.OK); assertThat(response.getHeaders().getContentType()) .isEqualTo(MediaType.APPLICATION_JSON); assertThat(response.getBody()) .isEqualTo("{ \"message\": \"Hello World!\" }"); } private String buildApiMethodUrl() { return String.format("http://localhost:%d/api/message", this.wireMockServer.port() ); } }
First, all strings given to WireMock (including the content of the body files) must use the UTF-8 character encoding.
Second, when we configure the body the returned HTTP response, we should select the used approach by following these rules:
- We should avoid reading the body of the HTTP response from a file because it makes our tests hard to read.
- We should prefer the
static
factory methods of theWireMock
class because the allow us to configure the body of the returned HTTP response without writing any boilerplate code. - If we cannot configure the body of the returned HTTP response by using the
static
factory methods of theWireMock
class, we should use the manual approach.
Next, we will find out how we can redirect an HTTP request to another location.
Redirecting HTTP Requests
If we want to redirect an HTTP request to another location, we can create the required ResponseDefinitionBuilder
object by using one of these three methods:
- The
permanentRedirect(String location)
method of theWireMock
class issues a permanent redirect. This means that it returns the HTTP status code 301 and redirects the request to the location given as a method parameter. - The
temporaryRedirect(String location)
method of theWireMock
class issues a temporary redirect. This means that it returns the HTTP status code 302 and redirects the request to the location given as a method parameter. - The
seeOther(String location)
method of theWireMock
class returns the HTTP status code 303 and redirects the request to the location given as a method parameter.
For example, if we want to ensure that our WireMock server issues a permanent redirect to the URL: 'https://www.testwithspring.com', we have to write a test method that looks as follows:
import com.github.tomakehurst.wiremock.WireMockServer; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; import org.springframework.web.client.RestTemplate; import static com.github.tomakehurst.wiremock.client.WireMock.*; import static org.assertj.core.api.Assertions.assertThat; @DisplayName("Configure the returned HTTP status code") class StubbingTest { private RestTemplate restTemplate; private WireMockServer wireMockServer; @Test @DisplayName("Should issue a permanent redirect") void shouldIssuePermanentRedirect() { givenThat(get(urlEqualTo("/api/message")).willReturn( permanentRedirect("https://www.testwithspring.com") )); String serverUrl = buildApiMethodUrl(); ResponseEntity<String> response = restTemplate.getForEntity(serverUrl, String.class ); assertThat(response.getStatusCode()) .isEqualTo(HttpStatus.MOVED_PERMANENTLY); assertThat(response.getHeaders().getLocation().toString()) .isEqualTo("https://www.testwithspring.com"); } private String buildApiMethodUrl() { return String.format("http://localhost:%d/api/message", this.wireMockServer.port() ); } }
We can now stub HTTP requests with WireMock. Let's summarize what we learned from this lesson.
Summary
This lesson has taught us five things:
- Stubbing is a technique that allows us to configure the HTTP response that is returned by our WireMock server when it receives a specific HTTP request.
- We can stub HTTP requests with WireMock by using the static
givenThat()
orstubFor()
methods of the WireMock class. - We can create the returned HTTP response by creating a new
ResponseDefinitionBuilder
object. - When we want to configure the returned HTTP response, we have to invoke the
willReturn()
method of theMappingBuilder
interface and pass aResponseDefinitionBuilder
object as a method parameter. - We can create new
ResponseDefinitionBuilder
objects by using either the manual approach or by leveraging thestatic
factory methods of theWireMock
class.
P.S. You can get the example application of blog post from Github.
How can I run this? like Run as Junit?
If "this" means the example application of this blog post, you can run the unit tests by using Maven or you can run them with your IDE after you have imported the Maven project.
Also, keep in mind that I removed the setup and teardown methods from the code examples of this blog post because they add no value to this blog post. That's why you cannot run these code examples (unless you implement these methods yourself).
Thanks for the reply Petri, I will try
Hi Petri Can I deploy the Wiremock code in Jboss server. From 2 days I am trying to figure it out please help me.
Hi,
Unfortunately I have never done that myself. However, maybe I can still help you out. What's the problem you are trying to solve?
Hi,
I am trying to deploy code with wiremock stubbing as well. So if I deploy it on jboss can i get response from the stubbing not from the actual controller.
Regards,
Sachin
If you are trying to implement an HTTP API which returns a stubbed HTTP response when it receives a specific HTTP request, you could either write the controller yourself or run WireMock as a standalone service.
It's kind of hard to give better advice because I don't why you want to stub HTTP APIs. Are you writing automated tests or doing manual testing?
Thanks for the suggestion and I am using Wiremock Standalone method to stub.
Since there was no easy document for wiremock I got confused, and I was trying to get response from my test case stubbing(But that is not possible I guess).
Thanks for Your quick replies cheers....