Automate API mocking with WireMock and Terraform
In this tutorial we build the Terraform based project which allows to install, setup and destroy WireMock API mocks in automated and reusable way.
Prerequisites
- Access to Debian Linux server. You can use VirtualBox locally or one of the cloud platforms (I'm using Digital Ocean in this tutorial).
- Terraform installed on your local machine.
- Docker installed (Mac or Windows).
1. Choosing the framework. WireMock
There are multiple open source application mocking frameworks available. We have created the list with the most popular ones.
For the purpose of this project, our 2 main requirements are:
- Mocking framework has to run as a stand alone application – this is important for containerisation.
- Mocking framework has to support dynamic provisioning of API mocks – so we can dynamically create / delete mock responses.
After doing some research I have picked the open source WireMock API mocking framework. It's a popular open source framework, with a good documentation and active community of users.
And it mee'ts our above requirements.
2. Design
WireMock stand alone version builds are published as .jar archive files which can be launched simply by java -jar
command.
WireMock also has admin API for provisioning mock mappings.
Downloading the .jar
file and running it directly in the virtual machine is one way of building the mock server.
However, we often want to quickly spin up 2, 3 or more backend API mock instances.
Creating the core Docker container image which can be provisioned with mock API endpoints dynamically is more practical approach. We are going to implement this.
Here is what we will do in below tutorial steps:
- Create the container image of WireMock standalone application.
- Start the new container with the above image, as backend API mock application.
- Create a set of mock responses as JSON files.
- Build the utility script which dynamically loads mock response JSON files as WireMock mappings.
3. Build the minimal WireMock Docker image
We will use the below Dockerfile to build the slim container image with running standalone WireMock in it.
FROM fabric8/java-alpine-openjdk8-jre:1.6.2
# meta
LABEL maintainer="popularowl.com"
# vars
ENV WIREMOCK_VERSION 2.23.2
# new directories
RUN mkdir /var/wiremock
RUN mkdir /var/wiremock/mappings
# default directory
WORKDIR /var/wiremock
# download wiremock stand alone build
RUN wget -O /var/wiremock/wiremock-standalone.jar https://repo1.maven.org/maven2/com/github/tomakehurst/wiremock-jre8-standalone/$WIREMOCK_VERSION/wiremock-jre8-standalone-$WIREMOCK_VERSION.jar
# expose wiremock ports
EXPOSE 8080 8443
# start wiremock
CMD java -jar /var/wiremock/wiremock-standalone.jar
We need the base container with JRE installed and the base container provided by RedHat's Fabric8 team fits well.
During the build we add instructions to download the recent standalone version of WireMock and run it on the new container upstart.
Run docker build -t wiremock-slim
to build the Docker image.
For convenience, I have published the completed Docker container image as popularowl/wiremock-slim on the DockerHub.
4. Setup Terraform project
Next, we need to setup a basic Terraform project which will create cloud virtual machine for our mock.
In this tutorial we are going to use the Terraform starter code from one of the previous step by step tutorials on Popularowl.
The source code of Terraform starter project is on GitHub and all you have to do is just clone the code to your local machine and use it.
5. Create the API mock mapping files
Next step is to create the actual mocked requests / responses.
WireMock allows 2 ways to provision stubbed responses.
Create the .json
files and upload them to mappings directory or dynamically provision stubs by making management api requests while WireMock is running.
In our case, in order to keep the base WireMock Docker image generic, we choose the second option. Generic base image means that we can start multiple containers from it and provision different stubs in each of them.
Management API allows us to submit JSON files with the request / response descriptions once WireMock is up and running.
In the files directory of basic Terraform project, create another directory called mocks.
In the mocks directory, create file users-mock.json
{
"request": {
"method": "GET",
"url": "/api/users"
},
"response": {
"jsonBody": [
{
"id": "12345",
"name": "name",
"surname": "surname",
"dob": "dob"
},
{
"id": "123456",
"name": "name",
"surname": "surname",
"dob": "dob"
}
],
"headers": {
"Content-Type": "application/json"
},
"status": 200
}
}
This file describes the mock endpoint, the request and the response which will be returned by API mock.
6. Create the mock provisioning utility
Next step is to create the utility script which is going to provision all the JSON mock files automatically.
We are going to use Python for this.
In files directory, create a file called setup_mocks.py
import json
import glob
import requests
MOCK_PATH = 'mocks/*.json'
WIREMOCK_ADMIN_URL = 'http://localhost:80/__admin/mappings'
FILES = glob.glob(MOCK_PATH)
for name in FILES:
print("Provisioning mock mapping with the file:", name)
with open(name) as json_file:
payload = json.load(json_file)
response = requests.post(WIREMOCK_ADMIN_URL, data=json.dumps(payload))
print("Status:", response.status_code, response.reason)
This script is looking for all the .json
files in mocks directory, and makes WireMock management API request for each one of them.
7. Bringing it all together
Finally, in order to automatically run all setup steps, we will update the main.tf
Terraform file.
It will first run setup.sh script which updates VM, installs Docker and starts WireMock container.
Second, it will call setup_mocks.py
file to dynamically provision all mock mappings we have created in .json
format.
After changes made, remote-exec
provisioner in the main Terraform file should look like this:
provisioner "remote-exec" {
inline = [
# add required file permissions
"chmod 755 /tmp/setup.sh",
"chmod 755 /tmp/setup_mocks.py",
# run the VM setup script
"/tmp/setup.sh",
"echo sleep 10s to allow WireMock container boot up; sleep 10",
# run mock mappings provisioning
"cd /tmp && python setup_mocks.py"
]
}
...
Note the 10 seconds sleep time - its there to allow for WireMock container to boot up.
Running the terraform apply
should now provision you the new virtual machine, install and run WireMock Docker container and dynamically provision mocked responses.
Summary
The goal of this tutorial was to create the template project for rapid building and configuring of backend application API mocks.
We have achieved this with the simple Terraform project and by containerising WireMock.
As always, the final completed source code for this tutorial you can find on GitHub. Comments and pull requests are welcome.