Pruebas en C# (.NET): revisión de frameworks y herramientas
Las pruebas de calidad son la base de un software confiable en la plataforma .NET. En el ecosistema de C# existen varios frameworks maduros para pruebas unitarias, de integración y de aceptación. En este artículo analizaremos las herramientas principales, sus características y proporcionaremos ejemplos prácticos de código.
Frameworks principales para pruebas unitarias
En .NET Core y .NET 5+, el soporte integrado para pruebas se implementa a través de tres frameworks principales:
- MSTest — el framework clásico de Microsoft, simple para principiantes.
- NUnit — un popular framework de código abierto con un rico conjunto de atributos.
- xUnit.net — una herramienta moderna, ligera y flexible, creada por el autor de NUnit.
Los tres son compatibles con Visual Studio, Rider y a través de dotnet CLI. La elección depende de las preferencias del equipo, pero xUnit y NUnit se consideran más flexibles para escenarios complejos.
Ejemplo de prueba con xUnit
Consideremos las pruebas de una calculadora simple usando xUnit:
using Xunit;
public class Calculator{ public int Add(int a, int b) => a + b; public int Divide(int a, int b) => b == 0 ? throw new DivideByZeroException() : a / b;}
public class CalculatorTests{ [Fact] public void Add_ShouldReturnSum_WhenTwoNumbers() { // Arrange var calc = new Calculator();
// Act var result = calc.Add(3, 5);
// Assert Assert.Equal(8, result); }
[Theory] [InlineData(10, 2, 5)] [InlineData(9, 3, 3)] [InlineData(7, 1, 7)] public void Divide_ShouldReturnQuotient(int a, int b, int expected) { var calc = new Calculator(); var result = calc.Divide(a, b); Assert.Equal(expected, result); }
[Fact] public void Divide_ShouldThrow_WhenDivideByZero() { var calc = new Calculator(); Assert.Throws<DivideByZeroException>(() => calc.Divide(5, 0)); }}El atributo [Fact] denota una prueba normal, mientras que [Theory] con [InlineData] permite ejecutar una misma prueba con diferentes datos de entrada.
Herramientas para objetos mock
En las pruebas unitarias, a menudo es necesario aislar la clase bajo prueba de dependencias externas (bases de datos, API, sistema de archivos). Para esto se utilizan frameworks de mock:
- Moq — el más popular, sintaxis simple, buena documentación.
- NSubstitute — más conciso, con interfaz fluida.
- FakeItEasy — API amigable para crear stubs rápidamente.
Ejemplo de uso de Moq
Supongamos que tenemos un servicio que envía correos electrónicos. Queremos probar la lógica sin enviar realmente:
using Moq;using Xunit;
public interface IEmailSender{ void Send(string to, string subject, string body);}
public class NotificationService{ private readonly IEmailSender _sender; public NotificationService(IEmailSender sender) => _sender = sender;
public void NotifyUser(string email, string message) { if (string.IsNullOrWhiteSpace(email)) throw new ArgumentException("Email is required"); _sender.Send(email, "Notification", message); }}
public class NotificationServiceTests{ [Fact] public void NotifyUser_ShouldCallSend_WhenValidEmail() { // Arrange var mockSender = new Mock<IEmailSender>(); var service = new NotificationService(mockSender.Object);
// Act service.NotifyUser("test@example.com", "Hello!");
// Assert mockSender.Verify(s => s.Send("test@example.com", "Notification", "Hello!"), Times.Once); }
[ También en la biblioteca
Registro para Swift: biblioteca SwiftyBeaver
Serialización de objetos en JavaScript (Node.js): guía completa
Colas de tareas para PHP: RabbitMQ, Beanstalkd y Gearman
Colas de tareas en Node.js: Bull, Bee-Queue, Kue e implementación en Redis
Caché en Swift (iOS/macOS): Redis, NSCache y otras soluciones