Тестирование в C# (.NET): фреймворки и инструменты
Тестирование — неотъемлемая часть профессиональной разработки на платформе .NET. Качественное покрытие кода тестами снижает количество багов, упрощает рефакторинг и повышает доверие к продукту. В экосистеме C# существует множество зрелых фреймворков и утилит, каждый из которых решает специфические задачи: от модульного тестирования до интеграционных проверок и UI-тестов. В этой статье мы разберём основные инструменты, их возможности и примеры использования.
Основные фреймворки для модульного тестирования
Модульное (unit) тестирование — основа пирамиды тестирования. В .NET Core / .NET 5+ стандартом де-факто стал xUnit.net, хотя NUnit и MSTest также активно используются.
xUnit.net
Современный, гибкий и наиболее популярный фреймворк. Работает по принципу "фактов" (facts) и "теорий" (theories).
- Факты (Fact) — простые тесты без параметров.
- Теории (Theory) — параметризованные тесты с данными из атрибутов
[InlineData]или[MemberData]. - Не требует атрибута
[TestClass]— любой публичный класс может содержать тесты.
using Xunit;
public class CalculatorTests
{
[Fact]
public void Add_ShouldReturnSum()
{
// Arrange
var calc = new Calculator();
// Act
var result = calc.Add(2, 3);
// Assert
Assert.Equal(5, result);
}
[Theory]
[InlineData(1, 2, 3)]
[InlineData(-1, -1, -2)]
public void Add_WithMultipleInputs_ShouldReturnCorrectSum(int a, int b, int expected)
{
var calc = new Calculator();
var result = calc.Add(a, b);
Assert.Equal(expected, result);
}
}
NUnit
Классический фреймворк с богатой историей. Отличается мощными атрибутами и поддержкой параметризации.
- Использует атрибуты
[Test],[TestCase],[SetUp]. - Поддерживает параллельное выполнение тестов.
- Удобен для сложных сценариев с тестовыми данными.
using NUnit.Framework;
[TestFixture]
public class CalculatorNUnitTests
{
[Test]
public void Subtract_ShouldReturnDifference()
{
var calc = new Calculator();
var result = calc.Subtract(10, 4);
Assert.That(result, Is.EqualTo(6));
}
[TestCase(5, 3, 2)]
[TestCase(0, 0, 0)]
public void Subtract_WithParameters_ShouldReturnCorrect(int a, int b, int expected)
{
var calc = new Calculator();
Assert.That(calc.Subtract(a, b), Is.EqualTo(expected));
}
}
MSTest
Встроенный фреймворк от Microsoft. Идеален для простых проектов и команд, работающих в экосистеме Visual Studio.
- Атрибуты:
[TestMethod],[TestClass],[DataRow]. - Тесная интеграция с Azure DevOps и CI/CD пайплайнами.
using Microsoft.VisualStudio.TestTools.UnitTesting;
[TestClass]
public class CalculatorMSTests
{
[TestMethod]
public void Multiply_ShouldReturnProduct()
{
var calc = new Calculator();
var result = calc.Multiply(4, 5);
Assert.AreEqual(20, result);
}
[DataRow(2, 3, 6)]
[DataRow(0, 100, 0)]
[DataTestMethod]
public void Multiply_WithDataRows_ShouldReturnCorrect(int a, int b, int expected)
{
var calc = new Calculator();
Assert.AreEqual(expected, calc.Multiply(a, b));
}
}
Библиотеки для mock-объектов и изоляции
При модульном тестировании часто необходимо изолировать тестируемый код от внешних зависимостей (БД, API, файловая система). Для этого применяются mock-фреймворки.
Moq
Самый популярный фреймворк для создания заглушек. Работает через лямбда-выражения и fluent-интерфейс.
- Создание mock:
var mock = new Mock<IUserRepository>(); - Настройка поведения:
mock.Setup(x => x.GetUser(It.IsAny<int>())).Returns(new User()); - Проверка вызовов:
mock.Verify(x => x.Save(), Times.Once);
using Moq;