Pruebas en C#: Unit, Integration, E2E — Guía completa para .NET

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 en C#: de Unit a E2E — cómo construir una arquitectura de calidad para verificaciones en .NET



La calidad del software depende directamente del sistema de pruebas. En el ecosistema de C# y .NET existe una pirámide de pruebas bien establecida: pruebas unitarias (unit), de integración (integration) y de extremo a extremo (end-to-end). En este artículo analizaremos cada nivel con ejemplos prácticos, mostraremos qué bibliotecas usar y proporcionaremos plantillas de código listas para usar.



1. Pruebas unitarias: la base de la estabilidad del código



Las pruebas unitarias verifican el funcionamiento de métodos, clases o componentes individuales de forma aislada de las dependencias externas (BD, API, sistema de archivos). El objetivo principal es encontrar rápidamente regresiones durante la refactorización.



Herramientas para C#

  • NUnit — framework clásico con atributos [Test], [TestCase].
  • xUnit — framework moderno de los creadores de NUnit, preferido en proyectos nuevos.
  • Moq — biblioteca para crear objetos mock.
  • FluentAssertions — para aserciones legibles.


Ejemplo de prueba unitaria con xUnit y Moq

Supongamos que tenemos un servicio de cálculo de descuento que consulta un repositorio de usuarios:



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 descuento return amount; }}

// Pruebapublic 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); }}


Consejo: Use [Theory] y [InlineData] en xUnit para pruebas parametrizadas — esto reduce la duplicación de código.



2. Pruebas de integración: verificación de la conexión entre componentes



Las pruebas de integración verifican cómo sus módulos interactúan con sistemas externos reales: bases de datos, colas, servicios web. A diferencia de las pruebas unitarias, aquí no se usan mocks — levantamos entornos reales.



Bibliotecas y enfoques

  • TestContainers — ejecuta contenedores Docker (PostgreSQL, SQL Server, Redis) directamente desde las pruebas.
  • WebApplicationFactory (de Microsoft.AspNetCore.Mvc.Testing) — crea un host de prueba para ASP.NET Core.
  • Respawn — limpia la BD entre pruebas sin recrear el contenedor.


Ejemplo de prueba de integración con TestContainers y WebApplicationFactory

Verificaremos que nuestra API guarda correctamente un usuario en 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 => { // Reemplazamos la cadena de conexión real por la del contenedor services.RemoveAll<DbContextOptions<AppDbContext>>(); se

Blogs

Book Recommendations