Are you tired of writing tests which have a lot of boilerplate code? If so, get started with Spock Framework >>

WireMock Tutorial: Introduction to Stubbing

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.

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:

  1. It identifies the HTTP request that triggers the configured HTTP response. We can identify the HTTP request by using WireMock’s request matching support.
  2. It configures the returned HTTP response. We can configure the returned HTTP response by using the willReturn() method of the MappingBuilder interface. When we invoke this method, we have to create a new ResponseDefinitionBuilder object and pass this object to the invoked method as a method parameter.
We can also use the 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()
        );
    }
}
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:

  1. Create a new ResponseDefinitionBuilder object by invoking the static aResponse() method of the WireMock class.
  2. Configure the returned HTTP status code by using the withStatus() method of the ResponseDefinitionBuilder 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()
        );
    }
}
We should select the used approach by following these rules:

  • 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 required ResponseDefinitionBuilder object by using the static factory methods of the WireMock 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:

  1. The name of the header.
  2. 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:

  1. Specify the returned HTTP headers by creating a new HttpHeaders object.
  2. Invoke the withHeaders() method and pass the created HttpHeaders 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()
        );
    }
}
Most of the time we should configure multiple HTTP headers by invoking the 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:

  1. Create a new ResponseDefinitionBuilder object by invoking the static aResponse() method of the WireMock class.
  2. Configure the content type of the returned HTTP response. We can do this by setting the value of the Content-Type header.
  3. Configure the body of the returned HTTP response by using the withBody() method of the ResponseDefinitionBuilder 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:

  1. Create the src/test/resources/__files directory.
  2. 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.
  3. Configure the location of the body file by using the withBodyFile() method of the ResponseDefinitionBuilder 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 to application/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 to application/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 to text/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()
        );
    }
}
There are two things I want to point out:

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 the WireMock 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 the WireMock 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 the WireMock 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 the WireMock 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 the WireMock 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() or stubFor() 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 the MappingBuilder interface and pass a ResponseDefinitionBuilder object as a method parameter.
  • We can create new ResponseDefinitionBuilder objects by using either the manual approach or by leveraging the static factory methods of the WireMock class.

P.S. You can get the example application of blog post from Github.

0 comments… add one

Leave a Comment