Testes de Integração C# com Docker: do A ao Z
\n\nTestes de integração são uma etapa criticamente importante no desenvolvimento de qualquer aplicação séria em C#. Eles verificam como diferentes componentes do sistema (banco de dados, APIs externas, sistemas de arquivos) funcionam juntos. No entanto, configurar o ambiente de teste muitas vezes se torna uma dor de cabeça: é preciso levantar servidores reais, limpar dados após os testes e lidar com a instabilidade do ambiente. O Docker resolve esses problemas fornecendo contêineres leves, isolados e reproduzíveis. Neste artigo, vamos abordar como configurar testes de integração C# com Docker do zero até um pipeline funcional.
\n\nPor que o Docker é ideal para testes de integração em C#?
\n\nA abordagem tradicional é usar bancos de dados SQL Server locais ou emuladores de serviços externos. Isso leva a problemas:
\n- \n
- Poluição de dados: os testes deixam lixo no BD, afetando outros testes. \n
- Incompatibilidade de ambientes: na máquina do desenvolvedor há uma versão do SGBD, no servidor CI há outra. \n
- Dificuldade de execução paralela: os testes entram em conflito por portas e recursos. \n
O Docker resolve isso de forma simples: cada teste (ou grupo de testes) recebe seu próprio contêiner isolado com a versão necessária do BD, Redis ou outro serviço. Os contêineres são leves, iniciam em segundos e são garantidamente destruídos após a conclusão dos testes. Para desenvolvedores .NET, isso é especialmente relevante graças à biblioteca Testcontainers for .NET, que automatiza o gerenciamento de contêineres diretamente do código de teste.
\n\nConfiguração do projeto: adicionando Docker aos testes C#
\n\nPara começar, vamos criar um projeto com testes de integração. Suponha que temos uma API web em .NET 8 que trabalha com PostgreSQL. Precisamos testar o endpoint de criação de usuário.
\n\nPasso 1: Instalação dos pacotes NuGet
\nAdicione os seguintes pacotes ao projeto de teste:
\ndotnet add package Testcontainers.PostgreSql\ndotnet add package Microsoft.AspNetCore.Mvc.Testing\ndotnet add package FluentAssertions\n\nTestcontainers.PostgreSql é um wrapper sobre o Docker SDK que gerencia contêineres PostgreSQL. Microsoft.AspNetCore.Mvc.Testing permite executar a aplicação web em memória para testes.
Passo 2: Criação da classe base para os testes
\nVamos criar uma classe abstrata que iniciará o contêiner com o BD antes dos testes:
\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\nEsta classe implementa IAsyncLifetime do xUnit, garantindo que o contêiner seja iniciado antes de todos os testes e parado após eles. A ConnectionString é obtida dinamicamente do contêiner — a porta pode ser qualquer uma disponível.
Passo 3: Escrevendo o teste com Testcontainers e WebApplicationFactory
\nAgora vamos escrever o teste em si. Usaremos WebApplicationFactory para criar um cliente HTTP de teste:
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