Pruebas de integración de C# con Docker: técnicas avanzadas

Entrenador de Python en Línea para Principiantes

Aprende Python fácilmente sin sobrecargarte de teoría. Resuelve tareas prácticas con verificación automática, recibe pistas y escribe código directamente en el navegador, sin instalar nada.

Start Course

Pruebas de integración de C# con Docker: nivel avanzado



Las pruebas de integración son una etapa críticamente importante en el desarrollo de C#, que permite verificar la interacción de los componentes del sistema con dependencias reales: bases de datos, colas de mensajes, API externas. El uso de Docker para este propósito se ha convertido en un estándar de la industria, pero a nivel avanzado surgen preguntas sobre aislamiento, rendimiento y ejecución paralela. En este artículo, analizaremos técnicas profesionales de pruebas de integración de C# con Docker, utilizando la biblioteca Testcontainers y configuraciones avanzadas.



1. Configuración de Testcontainers para .NET: infraestructura básica



La biblioteca Testcontainers para .NET permite gestionar mediante programación contenedores Docker en el entorno de pruebas. A diferencia de la ejecución manual de docker-compose, Testcontainers inicia y detiene automáticamente los contenedores para cada clase o módulo de prueba, garantizando un entorno limpio.



Instale el paquete a través de NuGet:

dotnet add package Testcontainers --version 3.9.0dotnet add package Testcontainers.PostgreSql --version 3.9.0dotnet add package Testcontainers.MsSql --version 3.9.0


Ejemplo de una clase base para pruebas de integración con PostgreSQL:

using Testcontainers.PostgreSql;using Xunit;

public class DatabaseFixture : IAsyncLifetime{ private readonly PostgreSqlContainer _container = new PostgreSqlBuilder() .WithImage("postgres:15-alpine") .WithDatabase("testdb") .WithUsername("testuser") .WithPassword("testpass") .Build();

public string ConnectionString => _container.GetConnectionString();

public async Task InitializeAsync() { await _container.StartAsync(); }

public async Task DisposeAsync() { await _container.StopAsync(); }}


Ahora cada clase de prueba puede usar este fixture para obtener una instancia aislada de la base de datos.



2. Aislamiento de pruebas y gestión del estado de los contenedores



El nivel avanzado requiere un control preciso sobre el aislamiento. En lugar de un contenedor para todo el conjunto de pruebas, utilice un contenedor por clase de prueba o incluso por prueba individual. Esto evita el estado "sucio" de la base de datos entre pruebas.



Implementación mediante el atributo Collection en xUnit:

[CollectionDefinition("Database collection")]public class DatabaseCollection : ICollectionFixture<DatabaseFixture>{}

[Collection("Database collection")]public class UserRepositoryTests{ private readonly DatabaseFixture _fixture;

public UserRepositoryTests(DatabaseFixture fixture) { _fixture = fixture; }

[Fact] public async Task CreateUser_ShouldPersistUser() { // Arrange await using var context = new AppDbContext(_fixture.ConnectionString); await context.Database.EnsureCreatedAsync(); var repo = new UserRepository(context);

// Act var user = new User { Name = "Test User" }; await repo.CreateAsync(user);

// Assert var savedUser = await context.Users.FindAsync(user.Id); Assert.NotNull(savedUser); }}


Para un aislamiento completo a nivel de prueba, use ITestOutputHelper y cree el contenedor dentro del método DisposeAsync:

public class IsolatedTest : IAsyncLifetime{    private PostgreSqlContainer _container;

public async Task InitializeAsync() { _container = new PostgreSqlBuilder().Build(); await _container.StartAsync(); }

public async Task DisposeAsync() { await _container.DisposeAsync(); }}


3. Ejecución paralela de pruebas y gestión de recursos



Una de las principales

Blogs

Book Recommendations