Testes em C#: Unit, Integration, E2E — nível avançado

Treinador Online de Python para Iniciantes

Aprenda Python facilmente sem sobrecarga teórica. Resolva tarefas práticas com verificação automática e escreva código diretamente no navegador.

Start Course

Introdução: Por que escrever testes em nível avançado?

O nível inicial de testes em C# geralmente se limita a simples Assert.Equal e testes unit isolados. No entanto, em projetos enterprise reais, isso não é suficiente. Bugs frequentemente surgem na interface entre componentes — na interação com banco de dados, APIs externas ou em lógica de negócios complexa com efeitos colaterais.

Testes avançados em C# (.NET) é a habilidade de construir uma pirâmide de testes, onde os testes unit são rápidos e isolados, os de integração verificam interações reais, e os testes E2E simulam o comportamento do usuário. Neste artigo, abordaremos ferramentas modernas: xUnit, Moq, FluentAssertions, Testcontainers e WebApplicationFactory. Você aprenderá a escrever testes confiáveis que não quebram durante refatorações e trazem confiança ao código.



1. Testes Unit Avançados: Mocks e Objetos Stub

Testes unit devem ser isolados de dependências externas. Em nível avançado, usamos bibliotecas para criar objetos mock, como Moq ou NSubstitute.



Configuração correta de Mock Objects

Em vez de criar stubs manualmente, use Mock.Of<T>() para configuração rápida. Exemplo com Moq e FluentAssertions:

public interface IEmailService{    Task SendAsync(string to, string subject);}

public class NotificationService{ private readonly IEmailService _emailService;

public NotificationService(IEmailService emailService) { _emailService = emailService; }

public async Task NotifyUserAsync(string email) { await _emailService.SendAsync(email, "Welcome!"); }}

// Teste[Fact]public async Task NotifyUserAsync_ShouldSendEmail(){ // Arrange var mockEmailService = new Mock<IEmailService>(); var service = new NotificationService(mockEmailService.Object);

// Act await service.NotifyUserAsync("test@example.com");

// Assert mockEmailService.Verify( x => x.SendAsync("test@example.com", "Welcome!"), Times.Once);}


Evite testar detalhes de implementação

A abordagem avançada é testar o comportamento, não as chamadas internas. Use Verify apenas para dependências críticas. Para as demais, verifique o resultado.



2. Testes de Integração: Banco de Dados e Serviços Externos

Testes de integração verificam se vários módulos funcionam juntos. Para .NET Core/5+, a ferramenta ideal é WebApplicationFactory (para ASP.NET Core) e Testcontainers (para conteinerização de dependências).



Configuração do WebApplicationFactory com BD real

Em vez de usar o provedor InMemory (que se comporta de forma diferente do BD real), use Testcontainers para iniciar PostgreSQL ou SQL Server no Docker:

public class IntegrationTestFixture : IAsyncLifetime{    private readonly TestcontainersContainer _dbContainer;

public string ConnectionString { get; private set; }

public IntegrationTestFixture() { _dbContainer = new TestcontainersBuilder<TestcontainersContainer>() .WithImage("postgres:15") .WithPortBinding(5432, true) .WithEnvironment("POSTGRES_USER", "test") .WithEnvironment("POSTGRES_PASSWORD", "test") .WithEnvironment("POSTGRES_DB", "testdb") .Build(); }

public async Task InitializeAsync() { await _dbContainer.StartAsync(); ConnectionString = $"Host=localhost;Port={_dbContainer.GetMappedPublicPort(5432)};" + $"Database=testdb;Username=test;Password=test"; }

public async Task DisposeAsync() { await _dbConta

Blogs

Book Recommendations