Tests d'intégration C# avec Docker : de A à Z
\n\nLes tests d'intégration sont une étape critique du développement de toute application sérieuse en C#. Ils vérifient comment les différents composants du système (base de données, API externes, systèmes de fichiers) fonctionnent ensemble. Cependant, la configuration de l'environnement de test devient souvent un casse-tête : il faut démarrer des serveurs réels, nettoyer les données après les tests et lutter contre l'instabilité de l'environnement. Docker résout ces problèmes en fournissant des conteneurs légers, isolés et reproductibles. Dans cet article, nous allons voir comment configurer les tests d'intégration C# avec Docker, de zéro jusqu'à un pipeline fonctionnel.
\n\nPourquoi Docker est-il idéal pour les tests d'intégration en C# ?
\n\nL'approche traditionnelle consiste à utiliser des bases de données SQL Server locales ou des émulateurs de services externes. Cela entraîne des problèmes :
\n- \n
- Pollution des données : les tests laissent des déchets dans la base de données, affectant les autres tests. \n
- Incompatibilité des environnements : la version du SGBD sur la machine du développeur diffère de celle du serveur CI. \n
- Difficulté d'exécution parallèle : les tests entrent en conflit pour les ports et les ressources. \n
Docker résout cela simplement : chaque test (ou groupe de tests) reçoit son propre conteneur isolé avec la version souhaitée de la base de données, Redis ou tout autre service. Les conteneurs sont légers, se lancent en quelques secondes et sont garantis d'être détruits après la fin des tests. Pour les développeurs .NET, cela est particulièrement pertinent grâce à la bibliothèque Testcontainers for .NET, qui automatise la gestion des conteneurs directement depuis le code des tests.
\n\nConfiguration du projet : ajouter Docker aux tests C#
\n\nPour commencer, créons un projet avec des tests d'intégration. Supposons que nous ayons une API web en .NET 8 qui fonctionne avec PostgreSQL. Nous devons tester le point de terminaison de création d'utilisateur.
\n\nÉtape 1 : Installation des packages NuGet
\nAjoutez les packages suivants au projet de test :
\ndotnet add package Testcontainers.PostgreSql\ndotnet add package Microsoft.AspNetCore.Mvc.Testing\ndotnet add package FluentAssertions\n\nTestcontainers.PostgreSql est une surcouche du SDK Docker qui gère les conteneurs PostgreSQL. Microsoft.AspNetCore.Mvc.Testing permet d'exécuter l'application web en mémoire pour les tests.
Étape 2 : Création d'une classe de base pour les tests
\nCréons une classe abstraite qui démarrera le conteneur de base de données avant les tests :
\nusing Testcontainers.PostgreSql;\nusing Xunit;\n\npublic abstract class IntegrationTestBase : IAsyncLifetime\n{\n private readonly PostgreSqlContainer _postgresContainer;\n\n protected string ConnectionString => _postgresContainer.GetConnectionString();\n\n protected IntegrationTestBase()\n {\n _postgresContainer = new PostgreSqlBuilder()\n .WithImage("postgres:16-alpine")\n .WithDatabase("testdb")\n .WithUsername("test")\n .WithPassword("test123")\n .Build();\n }\n\n public async Task InitializeAsync()\n {\n await _postgresContainer.StartAsync();\n }\n\n public async Task DisposeAsync()\n {\n await _postgresContainer.StopAsync();\n }\n}\n\nCette classe implémente IAsyncLifetime de xUnit, ce qui garantit le démarrage du conteneur avant tous les tests et son arrêt après. ConnectionString est obtenue dynamiquement depuis le conteneur — le port peut être n'importe quel port libre.
Étape 3 : Écriture du test avec Testcontainers et WebApplicationFactory
\nÉcrivons maintenant le test lui-même. Nous utiliserons WebApplicationFactory pour créer un client HTTP de test :
using Microsoft.AspNetCore.Mvc.Testing;\nusing FluentAssertions;\nusing System.Net.Http.Json;\n\npublic class UserApiTests : IntegrationTestBase\n{\n private readonly WebApplicationFactory<Program> _factory;\n\n public UserApiTests()\n