Тестирование в C# (.NET): обзор ключевых фреймворков и инструментов
Качественное тестирование — неотъемлемая часть разработки надёжного программного обеспечения на платформе .NET. В экосистеме C# существует множество зрелых фреймворков и утилит, которые помогают автоматизировать проверку кода на всех уровнях: от модульных тестов до интеграционных и UI-тестов. В этой статье мы рассмотрим основные инструменты, их особенности и приведём практические примеры использования.
Основные фреймворки для юнит-тестирования
Выбор фреймворка для модульного тестирования в .NET часто сводится к трём основным кандидатам: xUnit, NUnit и MSTest. Все они поддерживают атрибуты для определения тестов, assertions и запуск из командной строки или IDE.
xUnit.net
Современный, активно развивающийся фреймворк, созданный автором NUnit. Отличается минималистичным дизайном, отказом от атрибута [TestFixture] в пользу конструкторов для инициализации. Идеально интегрируется с .NET Core и .NET 5+.
using Xunit;
public class CalculatorTests
{
[Fact]
public void Add_ShouldReturnSum_WhenTwoNumbersAreProvided()
{
// Arrange
var calculator = new Calculator();
int a = 5, b = 3;
// Act
int result = calculator.Add(a, b);
// Assert
Assert.Equal(8, result);
}
[Theory]
[InlineData(2, 3, 5)]
[InlineData(0, 0, 0)]
[InlineData(-1, 1, 0)]
public void Add_ShouldHandleVariousCases(int a, int b, int expected)
{
var calculator = new Calculator();
int result = calculator.Add(a, b);
Assert.Equal(expected, result);
}
}
Ключевые особенности: [Fact] для обычных тестов, [Theory] с [InlineData] для параметризованных тестов, встроенная поддержка асинхронных тестов.
NUnit
Один из старейших фреймворков, широко используется в корпоративных проектах. Предоставляет богатый набор атрибутов ([SetUp], [TearDown], [TestCase]) и гибкие механизмы для управления контекстом тестов.
using NUnit.Framework;
[TestFixture]
public class CalculatorTests
{
private Calculator _calculator;
[SetUp]
public void Setup()
{
_calculator = new Calculator();
}
[Test]
[TestCase(1, 2, 3)]
[TestCase(10, -5, 5)]
public void Add_ShouldReturnCorrectSum(int a, int b, int expected)
{
int result = _calculator.Add(a, b);
Assert.That(result, Is.EqualTo(expected));
}
}
Отличия: требует атрибут [TestFixture] для класса, использует Assert.That(...) с constraint-моделью, что делает утверждения более читаемыми.
MSTest
Фреймворк от Microsoft, встроенный в Visual Studio. Прост в освоении, но менее гибок, чем xUnit или NUnit. Часто используется в проектах, где важна стандартизация на уровне компании.
using Microsoft.VisualStudio.TestTools.UnitTesting;
[TestClass]
public class CalculatorTests
{
[TestMethod]
public void Add_ShouldReturnSum()
{
var calculator = new Calculator();
int result = calculator.Add(2, 3);
Assert.AreEqual(5, result);
}
}
Библиотеки для mock-объектов и стабов
Для изоляции тестируемого кода от внешних зависимостей (БД, API, файловая система) используются mock-фреймворки. В .NET наиболее популярны Moq, NSubstitute и FakeItEasy.
Moq
Лидер по популярности. Позволяет легко создавать динамические mock-объекты через лямбда-выражения.
using Moq;
using Xunit;
public class OrderServiceTests
{
[Fact]
public void PlaceOrder_ShouldCallRepository_WhenValidOrder()
{
// Arrange
var mockRepo = new Mock<IOrderRepository>();
var service = new OrderService(mockRepo.Object);
var order = new Order { Id = 1, Amount = 100 };
// Act
service.PlaceOrder(order);
// Assert
mockRepo.Verify(r => r.Save(order), Times.Once);
}
}
Улучшение читаемости тестов: FluentAssertions
Библиотека FluentAssertions позволяет писать утверждения в естественном стиле, близком к человеческому языку. Это делает тесты самодокументируемыми.
using FluentAssertions;
using Xunit;
public class StringTests
{
[