Mocking Third-Party Services in Integration Testing

Eugenio Carocci
Geek Culture
Published in
4 min readOct 25, 2021
Photo by Glen Carrie on Unsplash

Current application development is more and more subjected to the use of third-party services for a variety of reasons, to speed up the development process, to rely on some robust and reliable solutions and many other reasonable reasons.

Yet, we need an effective way to be able to write and execute automated tests for our applications in an isolated environment, because, always remember that…

A code that cannot be tested is flawed.

In this article, I’ll explain the strategy that I’ve found effective to mock external services with a tool called MockServer while doing integration testing.

Suppose that you’re dealing with an application, that among other things, needs to validate an IBAN in different scenarios, for instance, while creating a new user. To do so different approaches can be adopted, starting from just validating the IBAN format (a weak check), up to the real-time validation interacting with a third-party service like this one.

So, first thing first, let’s give some details about this tool.

MockServer

I’ve found this great tool a while ago, and it’s been love at first sight ❤

This tool can be used as:

  • a mock configured to return specific responses for different requests.
  • a proxy recording and optionally modifying requests and responses.
  • both a proxy for some requests and a mock for other requests at the same time.

When the MockServer receives a request it matches the request against active expectations that have been configured, if no matches are found it proxies the request if appropriate otherwise a 404 is returned.

An expectation defines the action that is taken, for example, a response could be returned.

Example of mocking with MockServer

It is possible to use this tool in a variety of ways, yet my preferred approach is to use the official Docker image, which, at the time of writing, has been pulled more than 50 million times.

How does it work?

As briefly explained, the MockServer can be configured by defining expectations, which are blocks of request-response.

I’m in love with examples, I think they’re the best thing to let someone understand concepts, so let’s go back to our application that needs to validate an IBAN.

Probably we will execute an HTTPs request similar to the following one

GET https://iban-validator-service.com/api/v1/validate?iban=NL95RABO9809158653Authorization: Bearer api-key

So, we will need to define an expectation like this

{
"httpRequest": {
"method": "GET",
"path": "/api/v1/validate",
"queryStringParameters": {
"iban": [ "NL95RABO9809158653" ]
},
"headers": {
"Authorization": [
"Bearer api-key"
]
},
},
"httpResponse": {
"statusCode": 200,
"body": {
"bank_data": {
"bic": "RABONL2UXXX",
"branch": null,
"bank": "RABOBANK NEDERLAND",
"address": "CROESELAAN 18",
"city": "UTRECHT",
"state": null,
"zip": "3500 HG",
"phone": null,
"fax": null,
"www": null,
"email": null,
"country": "Netherlands",
"country_iso": "NL",
"account": "9809158653",
"bank_code": "RABO",
"branch_code": ""
},
"sepa_data": {
"SCT": "YES",
"SDD": "YES",
"COR1": "YES",
"B2B": "YES",
"SCC": "NO"
},
"validations": {
"chars": {
"code": "006",
"message": "IBAN does not contain illegal characters"
},
"account": {
"code": "002",
"message": "Account Number check digit is correct"
},
"iban": {
"code": "001",
"message": "IBAN Check digit is correct"
},
"structure": {
"code": "005",
"message": "IBAN structure is correct"
},
"length": {
"code": "003",
"message": "IBAN Length is correct"
},
"country_support": {
"code": "007",
"message": "Country supports IBAN standard"
}
},
"errors": []
}
}
}

With this expectation defined the mock-server will reply as if we would interact with the real service.

Obviously, this is a very simple example just to show the main idea behind the usage of this tool. More examples of expectations can be found on the official documentation page.

How can I use it?

As previously said, the MockServer can be found in different forms yet my preferred one is through the official Docker image.

Let’s suppose we have a PHP application with a Docker Compose cluster defined on the docker-compose.yml like this

version: '3.8'
# --------- #
# Services #
# --------- #
services:
nginx:
...
php-fpm:
networks:
internal:
aliases:
- php-fpm.internal
...
# --------- #
# Networks #
# --------- #
networks:
internal:

Then what we want to do is to add a MockServer instance for the IBAN validator service transforming the configuration to this one

version: '3.8'
# --------- #
# Services #
# --------- #
services:
nginx:
...
php-fpm:
networks:
internal:
aliases:
- php-fpm.internal
...
mock-iban-validator:
image: mockserver/mockserver
networks:
internal:
aliases:
- mock-iban-validator.internal
volumes:
- $PWD/docker/mock-server/iban-checker/:/config/
environment:
SERVER_PORT: 1080
MOCKSERVER_INITIALIZATION_JSON_PATH: /config/expectations.json
# --------- #
# Networks #
# --------- #
networks:
internal:

Note that inside the $PWD/docker/mock-server/iban-checker folder, a file called expectations.json is stored containing all the needed expectations.

With this configuration, the php-fpm service is able to ping the mock-iban-validator service, and in addition to that, is able to do something like the following

$ curl mock-iban-validator.internal:1080/api/v1/validate?iban=NL95RABO9809158653 -H "Authorization: Bearer api-key"

Obtaining the expected response.

Final Thoughts

I hope that this article helped some of you figure out the potential of this tool for the creation of integration testing!

Thanks for reading and feel free to add comments about your experiences :)

--

--