Wiremock Tutorial: Introduction To Wiremock

This Introductory Video Tutorial will Explain the Features of Wiremock and how to run Wiremock as a Standalone Server & as a part of JUnit Tests:

In this tutorial, we will be covering the basic concepts and details around the Wiremock tool. It can be used as a standalone HTTP server as well as within the JUnit tests as per the requirements.

This is a heavily used tool as it is open-source and has a great community of contributors. It comes under the category of Service virtualization tools.

Wiremock Tool Introduction

What Is Wiremock?

In simple terms, Wiremock is a mocking setup for integration tests. It’s simply a mock server that is highly configurable to return an expected response for a given request.

It is widely used during development and more importantly during Integration testing while a system or service talks to one or multiple external or internal dependencies/services.

Let’s try to understand more about integration testing in general and get to know how Wiremock can help to get past those challenges and make our lives easier.

Generally, when the word integration comes, what strikes us is an end to end integration between 2 communicating systems. Now, let’s look at it from the perspective of an application under test that uses some external service to get the job done.

For Example, let’s suppose that we are building an application for online travel or ticketing system and we have a module for PNR status check, that hits an external API provided by Indian Railways.

Now, how can we integration test our application with the external APIs?

There are 2 ways to do this:

  • First, is the Unit test approach, where we stub the interface that’s provided (or created in house) so that our system tests /validate the stubbed or fake response even before hitting the external API. This is nothing but a Unit test trying to mock an external dependency.
  • Second is testing with some test environment (or the actual production environment) of the external dependencies. However, there are several challenges with that approach such mentioned below:
    • External API systems might not always be available. i.e. We are heavily reliant or dependent on external systems and any downtime there will impact our tests and indirectly the development/release process.
    • Secondly, external APIs might or might not have a test environment. For Example, a PNR status check API might always require real PNR numbers to fetch and return responses.
    • A lot of times, there are costs involved in hitting an API. For example, suppose PNR check API charges Rs 100 for every 1000 requests. As integration tests are usually run during every regression (and most of the time with every commit), it might not be a cost-effective solution to hit such an API that costs us even for testing purposes.
    • An external API can not be configured to return the desired response. Even if possible, you’ll have to create a lot of test data to ensure different responses for different request inputs.
      For Example, you want to test error scenarios like an API is returning different status codes for different types of data. Now as the response is not under our control, we will need to create multiple sets of data to validate different possible scenarios or outcomes.

Let’s understand these concepts with the help of the below diagram.

Here we are comparing both the approaches of integration testing i.e. without a mock server using an actual implementation of the external dependency and using the mock server (Wiremock) which mocks responses to the requests received for the dependency.

In the latter case, it greatly reduces dependency and reliance on the actual implementation of dependency and gives a lot of configuration capabilities without compromising on quality and delivery schedules.

Wiremock Concepts

How Does Wiremock Respond To A Given Request?

As we know, Wiremock is a programmatic Mock server, the way it responds to a given request is by storing all the relevant mappings (or mocked responses) in a folder named as “mappings”

There’s a matcher component of Wiremock that matches incoming requests to the stored mappings and if a successful match is returned, then the first such match is returned as the response for the given request.

In case you are using the standalone version of Wiremock, once you run the Wiremock server, you’ll see the mappings folder that will get created in the Wiremock install/jar location directory.

Video Tutorial: Introduction To Wiremock Tool

How To Use Wiremock?

Now let’s see how we can use this tool with our integration tests.

It can be used in the following ways.

A Standalone Wiremock Server

As a standalone server, you can just create a simple Java application with Maven/Gradle dependency for Wiremock, and keep it as a running process.

This is a good alternative when you want to host your standalone server on some machine and use it as a single mocking server for the entire project or team. In standalone mode, this tool can also be executed, by downloading the standalone jar available here and simply run the jar.

For Example, suppose you want to deploy your Wiremock standalone instance to some server on cloud or an on-premise server, then you can simply run this jar and use the system IP to use it as a hosted service.

Let’s see some steps to run this in standalone mode (and configure different things like ports, mapping folders, etc)

#1) Run the Wiremock jar from the terminal (or command prompt for Windows users) like any other JAR file (from the Wiremock jar install directory).

java -jar wiremock-standalone-2.25.1.jar 

#2) By default, Wiremock runs on localhost:8080 (if the port is free for use then the above command will start the Wiremock server in a standalone mode) and you’ll see the output as below.

Wiremock runs on localhost

#3) Now once the server starts, you can visit any URL on localhost:8080

For Example, http://localhost:8080/get/user/1 – As currently there are no mocks being set, you’ll get a response as shown below.

Wiremock Response

#4) Now let’s try setting up a simple stub/mock for this URL and try hitting back the URL again. We will then validate that hitting the same URL is now returning the mocked or stubbed response.

curl -X POST --data 
'{ "request": { "url": "/get/user/1", "method": "GET" },
"response": { "status": 200, "body": "Here it is!\n" }}'
 http://localhost:8080/__admin/mappings/new

Let’s try understanding this CURL request first:

  • We are making a CURL POST request to http://localhost:8080/__admin/mappings/new – Now this is the location where all the mappings will be stored for the Wiremock server that we executed/started through the JAR file.
  • In the Curl request, we are defining request parameters like – URL and request method along with the response body in “response” section. This simply implies that whenever a GET request comes in with URL /get/user/1 then respond with the specified response body.

#5) Once the stubbed response is set (with the help of the above curl request), then we can try hitting the URL and see if we are getting back stubbed response from the Wiremock.

Let’s try hitting this URL in the browser – http://localhost:8080/get/user/1

If the mapping was successfully set, then you should get a response as shown below:

mapping was successfully set

Along With JUnit Tests As JUnit Rule Configuration

Wiremock server can be used with JUnit tests as a JUnit Rule setup. With this, JUnit takes care of the Wiremock lifecycle i.e. Wiremock starts and stops.

It’s mostly used in setups where you would like to start and stop the server after every test.

This has its own advantages of being isolated and has a high degree of configurability as opposed to a standalone setup where multiple people can end up using the same server and step over each other’s stubbed responses.

Let’s see a working example of this approach:

#1) Create a JUnit rule for the Wiremock server. This step essentially is like a test setup step where we are telling the JUnit runner to instantiate the Wiremock server before every test and stop the server after every test.

What this also means is that JUnit runner will take care of starting and stopping the Wiremock server, without explicitly doing so.

@Rule
 public WireMockRule wm = new WireMockRule(wireMockConfig().port(8080));

#2) Now we’ll write our test where we will first create our client (using okHttp) to execute requests against the desired endpoint.

// execute request through http client
    OkHttpClient client = new OkHttpClient();
    Request request = new Request.Builder()
        .url("http://localhost:8080/test/abc")
        .get()
        .build();

#3) But, you can notice here, that we still have not set any stub to be returned for our Wiremock instance. i.e. the above client will request a URL http://localhost:8080/test/abc that does not have any configured stub. In this case, the Wiremock server will return a 404 no content.

#4) Now in order to set a stub for the above URL for our Wiremock server instance, we will have to call the Wiremock’s stub static methods as shown below.

 private void configureStubs() {
    configureFor("localhost", 8080);
    stubFor(get(urlEqualTo("/test/abc"))
        .willReturn(aResponse().withBody("Test success!")));
  }

Here, you can see that we’ve used a couple of static methods like configureFor, stubFor, etc. All these methods are a part of the Wiremock Java library. (We will look at these methods in detail in our next tutorial/sections)

#5) Now with the configuration step done, we can simply execute the request through client and validate the response (depending on whatever is configured for the stub to return through Wiremock)

To sum up, here is how the entire code sample would look like:

public class WiremockJunitTest {

  @Rule
  public WireMockRule wm = new WireMockRule(wireMockConfig().port(8080));

  @Test
  public void assertWiremockSetup() throws IOException {
    // Arrange - setup wiremock stubs
    configureStubs();

    // execute request through the http client
    OkHttpClient client = new OkHttpClient();

    Request request = new Request.Builder()
        .url("http://localhost:8080/test/abc")
        .get()
        .build();

    // Act - call the endpoint
    Response response = client.newCall(request).execute();

    // Assert - verify the response
    assertEquals("Test success!", response.body().string());
    verify(exactly(1),getRequestedFor(urlEqualTo("/test/abc")));

  }

  // configure stubs for wiremock
  private void configureStubs() {
    configureFor("localhost", 8080);
    stubFor(get(urlEqualTo("/test/abc"))
        .willReturn(aResponse().withBody("Test success!")));
  }

}

Dependencies Required

It is available as:

  • A standalone JAR containing just the Wiremock dependency.
  • A fat jar containing Wiremock and all its dependencies.

Both the flavors are available as Gradle and Maven dependencies. More details are available at the official Maven repository here

Video Tutorial: Wiremock With JUnit Test

Conclusion

In this tutorial, we walked through the basic features of Wiremock and saw how it can be run as a standalone server and as a part of the JUnit tests using JUnit rules.

We also touched upon stubbing in brief and we will cover it in detail in our next tutorial.

NEXT Tutorial