Mocking – something we all need, and yet, usually, hate. Simply because writing mocks is a boring and cumbersome task. The good news – it doesn’t have to be like that. There are so many good alternatives that make mocking easier: From libraries that ease the process of writing the mock, though contract testing with Pact (which solve the problem in a totally different way) to automatically generating mocks using Swagger/Open API spec. All are really good solutions – but today I want to focus on WireMock: A tool that really makes mocking a fun.
WireMock is a mocking tool (like the name implied). It can be used programmatically to create a mock, but the interesting part is the interactive mode. In the interactive mode, you first use WireMock to record requests to the real API (by proxying the requests and responses). Once the recording completed, WireMock produces mocking from the proxied requests and responses. Using the interactive mode eliminate all the hard work of writing a mock and let you focus on your actual tests. Because the mocks are based on the recording of the actual traffic, the mock is identical to the original API, which makes the tests more reliable. And lastly – updating the mock is as simple as re-recording the requests/responses. Let’s take a look at a real example (or just take a look at Kamus end-to-end tests).
Mocking Kubernetes API
While working on Kamus (a secret encryption/decryption for Kubernetes), I had to mock Kubernetes API. Let’s see what how easy it is using WireMock!
After downloading and running WireMock (
java -jar java -jar wiremock-standalone-2.18.0.jar), open
http://localhost:8080/__admin/recorder/ in your browser:
Fill the details of the target API (in my case, it is the local Kubernetes proxy URL –
http://localhost:8001), and hit “Record”. Now, all we need to do is point our code to
http://localhost:8080 instead of Kubernetes API, and run it. Now it’s time to play with our API – make sure to call every functionality so WireMock call record all the different requests and responses (and yes, this should include error cases). This is very similar to how you explorer an application with Zaproxy, just for different purposes…
After the code run completed, hit “Stop” in WireMock UI. Now if you’ll look at the folder when you run WireMock, you’ll notice a new folder there with the name “mapping”. This folder contains all the requests and responses recorded (see an example here).
Putting it all together
Now that we have the recording ready, all that is left is running the tests. To run the tests, I use
docker-compose. This how the
docker-compose.yaml look like in Kamus:
version: '3' services: encryptor: image: $ENCRYPTOR_IMAGE environment: - ASPNETCORE_ENVIRONMENT=Development decryptor: image: $DECRYPTOR_IMAGE environment: - ASPNETCORE_ENVIRONMENT=Development - Kubernetes__ProxyUrl=http://wiremock:8080 black-box: build: context: ../ environment: - ENCRYPTOR=http://encryptor:9999/ - DECRYPTOR=http://decryptor:9999/ - TEAMCITY_PROJECT_NAME=api - PROXY_URL=http://zap:8090 - KUBERNETES_URL=http://wiremock:8080 volumes: - ./reports:/reports wiremock: build: context: ../Wiremock
I defined 4 services – Kamus API (encryptor and decryptor), tests, and WireMock. Notice the
KUBERNETES_URL environment variable – see how it points to Wiremock. Running WireMock in docker is really simple – this is the docker file:
FROM openjdk:8-stretch WORKDIR /wiremock RUN wget http://repo1.maven.org/maven2/com/github/tomakehurst/wiremock-standalone/2.17.0/wiremock-standalone-2.17.0.jar COPY . . CMD ["java", "-jar", "wiremock-standalone-2.17.0.jar"]
Notice the copy instruction – this where I copy the mapping folder.
Now that we have all set – all we need to do in order to run the tests is a simple docker compose command (take a look at Kamus CI if you don’t believe me):
docker-compose up --build --exit-code-from black-box.
The tests will run, and the code will use WireMock instead of Kubernetes API.
Isn’t mocking with WireMock fun?