Tests d'intégration C# avec Docker : niveau avancé
\nLes tests d'intégration sont une étape clé de l'assurance qualité dans les applications .NET modernes. L'utilisation de Docker permet de créer des environnements isolés et reproductibles, aussi proches que possible de la production. Dans cet article, nous explorerons les techniques avancées de tests d'intégration C# avec Docker : de la configuration de Testcontainers à l'organisation des pipelines CI/CD.
\nCe contenu s'adresse aux développeurs déjà familiarisés avec les bases des tests unitaires et les concepts fondamentaux de Docker. Nous approfondirons la gestion du cycle de vie des conteneurs, le travail avec plusieurs services, le débogage et l'optimisation du temps d'exécution des tests.
\n\n1. Configuration de Testcontainers pour .NET
\nTestcontainers est une bibliothèque qui gère les conteneurs Docker à partir du code de test. Elle crée, lance et arrête automatiquement les conteneurs, garantissant l'isolation de chaque test.
\nPour commencer, installez le package dans votre projet de test :
\ndotnet add package Testcontainers\nUn exemple de base — tester un dépôt avec PostgreSQL :
\nusing Testcontainers.PostgreSql;\nusing Xunit;\n\npublic class UserRepositoryTests : IAsyncLifetime\n{\n private readonly PostgreSqlContainer _postgresContainer;\n\n public UserRepositoryTests()\n {\n // Configurer le conteneur avec PostgreSQL\n _postgresContainer = new PostgreSqlBuilder()\n .WithImage("postgres:15")\n .WithDatabase("testdb")\n .WithUsername("test")\n .WithPassword("test123")\n .WithCleanUp(true)\n .Build();\n }\n\n public async Task InitializeAsync()\n {\n // Lancer le conteneur avant tous les tests\n await _postgresContainer.StartAsync();\n }\n\n public async Task DisposeAsync()\n {\n // Arrêter et supprimer le conteneur\n await _postgresContainer.DisposeAsync();\n }\n\n [Fact]\n public async Task AddUser_ShouldCreateUser()\n {\n // Obtenir la chaîne de connexion au conteneur\n var connectionString = _postgresContainer.GetConnectionString();\n var repository = new UserRepository(connectionString);\n\n await repository.AddUserAsync(new User { Name = "Test User" });\n var user = await repository.GetUserByNameAsync("Test User");\n\n Assert.NotNull(user);\n Assert.Equal("Test User", user.Name);\n }\n}\nImportant : utilisez IAsyncLifetime pour gérer le conteneur. Cela garantit que chaque classe de test reçoit une instance fraîche de la base de données.
2. Architecture multi-conteneurs avec Docker Compose
\nLes applications réelles dépendent de plusieurs services : base de données, file d'attente de messages, cache. Testcontainers prend en charge Docker Compose, ce qui permet de lancer toute une infrastructure.
\nInstallez le package supplémentaire :
\ndotnet add package Testcontainers.Compose\nExemple de fichier docker-compose.test.yml :
version: '3.8'\nservices:\n postgres:\n image: postgres:15\n environment:\n POSTGRES_USER: test\n POSTGRES_PASSWORD: test\n POSTGRES_DB: testdb\n redis:\n image: redis:7-alpine\nUtilisation dans le test :
\nusing Testcontainers.Compose;\n\npublic class OrderServiceTests\n{\n private readonly DockerComposeContainer _compose;\n\n public OrderServiceTests()\n {\n _compose = new DockerComposeContainer()\n .WithComposeFilePath("docker-compose.test.yml")\n .WithEnvironment("ASPNETCORE_ENVIRONMENT", "Testing")\n .Build();\n }\n\n [Fact]\n public async Task CreateOrder_ShouldSaveToDbAndCache()\n {\n await _compose.StartAsync();\n \n var dbConnection = _compose.GetConnectionString("postgres", 5432);\n var redisConnection = _compose.GetConnectionString("redis", 6379