Why you should use Wiremock for API development and testing

Introduction

API stands for Application Programming Interface. We are used to GUI (Graphical User Interface) based applications and that is what is needed for most users who just want to get their work done e.g. booking air-tickets. However, APIs are a special class of software that help software developers to interact with other software “programmatically”. For example, as a software developer, if I am trying to build a website that helps find cheapest flights, I might need to access prices of all the airlines, compare them and present the lowest rate to users. Now, if I have to do all that in my code, I need an ability to programmatically interact with the airline websites. And, thats where APIs come into picture. I can call APIs provided by different airlines, get the price and show the flights on GUI in increasing order of price. Now, this is just one example of an API (which is based on HTTP protocol); APIs can be of many different types. In this article, I want to introduce a tool called Wiremock and its benefits in API development and testing.

Have you ever packed Christmas gifts for your kids and pretended it came from Santa? Well, the kids would certainly be ecstatic and thats the whole purpose of gifts right? Seeing your kids happy?

Well, wiremock does the same for API developers and testers.

What is Wiremock?

Wiremock is a mock server that helps you mock API responses you depend on that doesn’t exist or isn’t complete or costs money or simply put – is not in your control. Even when the API exists, it helps in testing of edge cases and failure modes that the real API won’t reliably produce. Because of this reason, application development and testing is expedited.

Let’s understand this with an example – Suppose, you are testing a e-commerce website. To test the order life-cycle end to end, you are dependant on payment service which is a third party service you have no control over. It happens so that payment service is often unavailable and this leads to delay at your end. To eliminate this terrible dependency, you can take the exact response that you expect to receive from payment service and give it to wiremock. After that, tell your application to go to wiremock every time it has to interact with the payment service. And just like that, you start receiving expected response and you are able to test end to end workflow successfully.

Wiremock Illustration
Wiremock Illustration

Working with wiremock

Enough talking. Let’s set up wiremock and see its power in action.

Wiremock can be used in either of the following ways –

  1. Add as a dependency in your project i.e. maven or gradle
  2. As a standalone server

In this article, we will look at the 2nd option, primarily because standalone wiremock server can be easily deployed on your company’s server. This makes sure that everyone in your organization can take advantage of single wiremock server rather than duplicating the set-up in every project.

Using a jar file, wiremock can be started like this –

java -jar wiremock-standalone-2.27.2.jar

The above command will start the wiremock server on your localhost:8080. It runs on port 8080 by default. If you want to start it on a different port, just pass an argument to above the statement e.g. –port 9999

wiremock - how it looks like when it starts
wiremock – how it looks like when it starts

When wiremock runs for the first time, it creates two folders – mappings and __files in the same folder where wiremock jar file exists. Wiremock expects us to configure mocks by placing JSON specifications under the mappings folder. When it receives a new request, wiremock searches for a matching mock mappings folder and returns response, if a match is found.

__files folder can store downloadable files. Sometimes, calling an API can download files like PDF, CSV etc. If you would like to mock file download, such files go under this folder.

JSON specifications look like this –

{
    "request": {
        "method": "GET",
        "url": "/payment-gateway/process-payment"
    },
    "response": {
        "status": 200,
        "headers":{
            "content-type": "application/json"
        },
        "jsonBody": {
            "payment": "approved"
        }
    }
}

As you can see, the JSON specification, basically, describes the expected request and response for the endpoint “/payment-gateway/process-payment”. What this means is –

when a request is made to https://<your-domain>/payment-gateway/process-payment”, it will respond with the response specified above.

In the image below, you can see the wiremock directory on my machine. There are mappings and __files folders and wiremock jar file. Under mappings folder, I have placed payment.json file which acts as a mock for payment endpoint.

wiremock directory
wiremock directory

In our case, we started the wiremock server on our localhost, so we will get the above response when we hit localhost:8080/payment-gateway/process-payment. Let’s do it –

calling mocked endpoint from postman
calling mocked endpoint from postman

In the above example, I mocked payment approval. You can mock other scenarios like rejection, server unreachable etc. by adding multiple JSON specifications under the mappings folder. When you have multiple mocked responses, you can define the priority of mocks by adding “priority: <integer>” at the top of the json file. One important thing to note here is – if any file is updated in the directory after wiremock server was started, we need to restart the server for the changes to take effect.

In the above example, we mocked response for the payment service just based on matching the URL. However, there are so many parameters that can be used for request matching like headers, query parameters, request body, cookies and many more. Furthermore, you can also inject faults like response delay by adding a fixed or variable delay to the mocks, if you would like to observe system’s behaviour under latency.

Logging and Debugging

Wiremock is a software and like other software, sometimes, wiremock might not work as expected either due to our lack of knowledge or a bug in wiremock itself. And, when such time arrives (trust me it will, every single day. Not because of bug in wiremock but due to lack of knowledge :P), you will thank wiremock’s Admin API.

Wiremock’s Admin API basically exposes several rest endpoints that let us configure wiremock on the fly and peek into things happening behind the scenes. It also let us add new or modify existing mocks.

For example, if a certain mock is not working and if you would like to see if it was staged correctly on wiremock server, you can call this admin endpoint and get list of all the active mocks – GET localhost:8080/__admin/mappings

If you would like to see all the requests received by wiremock since it was last started, you can call this endpoint – GET localhost:8080/__admin/requests. On the other hand, if you would like to get a list of all the unmatched (requests received by wiremock but no match was found) requests, you can call this endpoint – GET localhost:8080/__admin/requests/unmatched

If you would like to explore the full potential of Admin API please refer this page.

In addition to Admin API, you can also monitor the wiremock logs in the command line terminal where you ran the jar. By default, it will log all the interactions.

Conclusion

Isn’t wiremock simple yet powerful? If you were developing/testing end to end workflow for checkout feature that involves payment, you could just use wiremock for various scenarios – payment is approved, payment is rejected, server returned 502, user is unauthorized etc. Imagine having to depend on payment service, which you have no control over, for development and testing. It’s not impossible to test with the actual payment service but imagine going through all that pain. There are so many things that can go wrong. Service downtime is a known culprit but there are others – managing real financial transactions, having to bring down service for edge case scenarios, having to reject a transaction etc. Using wiremock, we can avoid this entirely plus accelerate the development and testing of our software.

Leave a Comment

Your email address will not be published. Required fields are marked *