Integration Testing in Containers (2024)

Insights + News/Expert Opinions

Integration Testing in Containers (1)

Chris Butler
Senior Consultant - .Net

This blog post aims to guide you through an alternative way of running integration tests within your project. We look to make use ofTestcontainerswhich support tests with throwaway instances of Docker containers. A list of the pre-configured containers can befound here. This means we can run tests without going to a deployed instance of the service we look to integrate with, saving time on round-trip-times. All code talked about in this post will beavailable here.

For the purposes of our project, an integration test is defined as an automated test written to test the interaction between code that we have written with a third party service. The goal is to prove that the code can communicate as expected with the third party service so that we can identify any defects before it reaches a later stage of the development cycle.

We will use Docker containers. To follow along, you will need to have Docker (or equivalent) set up and running. Testcontainers will spin up container instances which will be used to execute tests against. Each test will have a dedicated container instance so that tests can be run in parallel without affecting other tests.

By using a container, we can execute tests locally without depending on the third party service to host an instance and we can execute each test against a new instance of the third party service without having to set up anything locally.

Creating an Integration Test

The class under test

For this example, we will test a class that will integrate with Redis. I’ve created two projects, one to contain the class that will be tested and another to execute tests.

// https://github.com/chris31389/redis-integration-tests/blob/main/RedisExample/Cache.cs using StackExchange.Redis; namespace RedisExample; public class Cache { private readonly IConnectionMultiplexer _connectionMultiplexer; public Cache(IConnectionMultiplexer connectionMultiplexer) { _connectionMultiplexer = connectionMultiplexer; } public async Task SetAsync(string key, string value) { var database = _connectionMultiplexer.GetDatabase(); await database.StringSetAsync(key, value); } 

Writing the test

The test we want to execute needs to interact with the instance of redis. We need each test to:

  1. Spin up an instance of the redis container
  2. Create an instance of the Cache with a link to the instance of redis
  3. Setup the test (optional)
  4. Execute the test
  5. Assert whether the test passed
  6. Dispose of the instance of the redis container

The DotNet NuGetTestcontainers(currently version 2.20) gives us the ability to spin up container instances per test. For Redis there is a pre-configuredRedisTestcontainerwe can use to provide us an instance of redis within a container.

// https://github.com/chris31389/redis-integration-tests/blob/main/RedisExample.IntegrationTests/CacheTests.csusing DotNet.Testcontainers.Builders;using DotNet.Testcontainers.Configurations;using DotNet.Testcontainers.Containers;using FluentAssertions;using StackExchange.Redis;namespace RedisExample.IntegrationTests;public class CacheTests : IAsyncLifetime{ // The class that will create instances of redis based of the configuration we pass in private readonly TestcontainerDatabase _testcontainers = new TestcontainersBuilder<RedisTestcontainer>() .WithDatabase(new RedisTestcontainerConfiguration()) .Build(); // This is executed before each test is executed public async Task InitializeAsync() { // 1. Spin up an instance of the redis container await _testcontainers.StartAsync(); // Setup a link to the instance of redis _connectionMultiplexer = await ConnectionMultiplexer.ConnectAsync(_testcontainers.ConnectionString); } private IConnectionMultiplexer? _connectionMultiplexer; [Fact] public async Task GivenKeyValuePair_WhenICache_ThenItIsPersisted() { // Arrange // 2. Create an instance of the Cache with a link to the instance of redis var cache = new Cache(_connectionMultiplexer!); // Act // 4. Execute the test await cache.SetAsync("myKey", "myValue"); // Assert var database = _connectionMultiplexer!.GetDatabase(); var actualValue = await database.StringGetAsync("myKey"); // 5. Assert whether the test passed actualValue.Should().Be("myValue"); } // This is executed after each test is executed public async Task DisposeAsync() { // 6. Dispose of the instance of the redis container await _testcontainers.DisposeAsync().AsTask(); } }

Conclusion

This blog post has shown that we can execute integration tests locally which target a Docker container. Anyone with Docker installed and running can clone this repository, build and test it. They are not required to install or provision an instance of Redis to execute these tests. This should help speed up and improve the development process.

There are limitations:

  • Not all third party services can be containerised (e.g. Azure Service Bus)
  • Not every third party service has a pre-made setup class, which means there will need be a Testcontainer class written for the missing service.

This repository is actively being developed and there are already people developing a cosmos and azurite Testcontainer setup class. As these get introduced, it will be quicker and easier to get started with these services.

Next Blog Post

Are we Failing to Address Bias in AI? Examining the Realities and Solutions

Don't miss the latest from Ensono

PHA+WW91J3JlIGFsbCBzZXQgdG8gcmVjZWl2ZSB0aGUgbGF0ZXN0IG5ld3MsIHVwZGF0ZXMgYW5kIGluc2lnaHRzIGZyb20gRW5zb25vLjwvcD4=

Keep up with Ensono

Innovation never stops, and we support you at every stage. From infrastructure-as-a-service advances to upcoming webinars, explore our news here.

Blog Post | June 18, 2024 | Industry trends

Journey to Cloud Systems: From Mainframe Monoliths to Cloud Microservices

Blog Post | April 16, 2024 | Technology trends

VMware and Broadcom acquisition: What it means for you and how you should optimize

Blog Post | March 12, 2024 | Best practices

Transforming Cloud Projects with Agile: A Path to Enhanced Efficiency and Innovation

Start your digital transformation today.

Let's talk

Integration Testing in Containers (2024)

References

Top Articles
Latest Posts
Article information

Author: Kareem Mueller DO

Last Updated:

Views: 6808

Rating: 4.6 / 5 (46 voted)

Reviews: 93% of readers found this page helpful

Author information

Name: Kareem Mueller DO

Birthday: 1997-01-04

Address: Apt. 156 12935 Runolfsdottir Mission, Greenfort, MN 74384-6749

Phone: +16704982844747

Job: Corporate Administration Planner

Hobby: Mountain biking, Jewelry making, Stone skipping, Lacemaking, Knife making, Scrapbooking, Letterboxing

Introduction: My name is Kareem Mueller DO, I am a vivacious, super, thoughtful, excited, handsome, beautiful, combative person who loves writing and wants to share my knowledge and understanding with you.