Testes em C#: Unit, Integration, E2E — Guia Completo para .NET

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

Testes em C#: de Unit a E2E — como construir uma arquitetura de qualidade para verificações em .NET



A qualidade do software depende diretamente do sistema de testes. No ecossistema C# e .NET, existe uma pirâmide de testes bem estabelecida: testes unitários (unit), de integração (integration) e ponta a ponta (end-to-end). Neste artigo, vamos analisar cada nível com exemplos práticos, mostrar quais bibliotecas usar e fornecer modelos de código prontos.



1. Testes unitários: a base da estabilidade do código



Testes unitários verificam o funcionamento de métodos, classes ou componentes individuais isolados de dependências externas (banco de dados, API, sistema de arquivos). O objetivo principal é encontrar rapidamente regressões durante a refatoração.



Ferramentas para C#

  • NUnit — framework clássico com atributos [Test], [TestCase].
  • xUnit — framework moderno dos criadores do NUnit, preferível em novos projetos.
  • Moq — biblioteca para criar objetos mock.
  • FluentAssertions — para asserts mais legíveis.


Exemplo de teste unitário com xUnit e Moq

Suponha que temos um serviço de cálculo de desconto que consulta um repositório de usuários:



public interface IUserRepository{    bool IsPremiumUser(int userId);}

public class DiscountService{ private readonly IUserRepository _userRepo; public DiscountService(IUserRepository userRepo) => _userRepo = userRepo;

public decimal CalculateDiscount(int userId, decimal amount) { if (_userRepo.IsPremiumUser(userId)) return amount * 0.9m; // 10% de desconto return amount; }}

// Testepublic class DiscountServiceTests{ [Fact] public void CalculateDiscount_ForPremiumUser_Returns90Percent() { // Arrange var mockRepo = new Mock<IUserRepository>(); mockRepo.Setup(r => r.IsPremiumUser(It.IsAny<int>())).Returns(true); var service = new DiscountService(mockRepo.Object);

// Act var result = service.CalculateDiscount(1, 100m);

// Assert Assert.Equal(90m, result); }}


Dica: Use [Theory] e [InlineData] no xUnit para testes parametrizados — isso reduz a duplicação de código.



2. Testes de integração: verificando a conexão entre componentes



Testes de integração verificam como seus módulos interagem com sistemas externos reais: bancos de dados, filas, serviços web. Diferente dos testes unitários, aqui não usamos mocks — levantamos ambientes reais.



Bibliotecas e abordagens

  • TestContainers — executa contêineres Docker (PostgreSQL, SQL Server, Redis) diretamente dos testes.
  • WebApplicationFactory (do Microsoft.AspNetCore.Mvc.Testing) — cria um host de teste ASP.NET Core.
  • Respawn — limpa o banco de dados entre os testes sem recriar o contêiner.


Exemplo de teste de integração com TestContainers e WebApplicationFactory

Vamos verificar se nossa API salva corretamente um usuário no PostgreSQL:



public class UserApiIntegrationTests : IClassFixture<TestContainersFixture>{    private readonly HttpClient _client;    private readonly TestContainersFixture _fixture;

public UserApiIntegrationTests(TestContainersFixture fixture) { _fixture = fixture; var factory = new WebApplicationFactory<Program>() .WithWebHostBuilder(builder => { builder.ConfigureTestServices(services => { // Substituímos a string de conexão real pelo contêiner services.RemoveAll<DbContextOptions<AppDbContext>>(); se

Blogs

Book Recommendations