back to xoc3.io

2025-03-21 - No-Internet Integration Tests

For work I setup a fast, simple, and effective integration testing framework. It runs an application and dependencies through docker compose in an internal network that cannot access the internet.

Restricting internet access in tests is important for me, because as software scales, someone is bound to accidentally introduce code in tests that access the broader network. Then your tests break when something is down in the company network or internet and tests become flaky.

Test Containers is a popular way to containerize tests. I had used it years ago at my last job, but I didn't want to set it up here for a few issues:

Again at my last job, I had used WireMock as a mock webservice. WireMock is a java-based project and while it doesn't what language it is based on since it runs in docker, I have a bias against java-based projects. Java projects are often bloated/large binary sizes. I searched around and found a newer-ish mock server called Mockoon. Mockoon is great, the entire mock server configuration is contained in a single json file. It also comes with an electron based-UI you can use just for editing that schema file. You can import mocks from a swagger OpenAPI configuration or run a proxy from the Mockoon server to help generate mocks. It was a great experience compared to what I remembered with WireMock ~5 ago.

The integration test also has a postgres instance. The postgres instance starts with an empty database/schema, then has a schema applied to it with dbmate. Dbmate is a language agnostic sql changeset management tool, there are so many changeset management tools built into different ORMs, but really like having a tool that is agnostic. We may refactor our application to use a different language or db framework later and not being locked into a specific ORM's changeset tool is one less headache to think about. The schema is applied nearly instantly. After that, mock data is inserted from another container by connecting to the db from the internal network.

And finally, the application is run in a container on the docker network and the tests are run in a separate container.

Here is a sample docker-compose.yaml file that demonstrates how the containers are all setup:

And then you can just have a simple shell script that can patch the integration test together:

This approach to integration testing can be very fast. In my case, it currently takes about 45 seconds for downloading/pulling docker images. Then only 15 seconds for starting the containers, setting up the schema, and running some tests. My tests currently run on Github Actions. The state docker layer caching between builds on Github Actions kinda sucks, so I'm hoping to try it in CircleCI or another service later on. But there you have it! A simple template for to how you can setup isolated integration testing using docker compose.