Какую библиотеку используют для создания моков (mock-объектов) в C#?

Ответ

В экосистеме .NET для создания моков (mock-объектов) в юнит-тестах наиболее популярной и широко используемой библиотекой является Moq. Она предоставляет интуитивно понятный fluent-синтаксис для настройки поведения зависимостей.

Пример использования Moq:

// Интерфейс зависимости
public interface IDataRepository
{
    int GetRecordCount();
}

// Класс, который тестируем
public class ReportService
{
    private readonly IDataRepository _repository;
    public ReportService(IDataRepository repository) => _repository = repository;
    public bool HasData() => _repository.GetRecordCount() > 0;
}

// Юнит-тест с Moq
[Test]
public void HasData_ReturnsTrue_WhenRepositoryHasRecords()
{
    // 1. Arrange (Подготовка)
    var mockRepository = new Mock<IDataRepository>();
    // Настраиваем мок: при вызове GetRecordCount() возвращаем 5
    mockRepository.Setup(repo => repo.GetRecordCount()).Returns(5);

    var service = new ReportService(mockRepository.Object);

    // 2. Act (Действие)
    bool result = service.HasData();

    // 3. Assert (Проверка)
    Assert.IsTrue(result);
    // Дополнительная проверка, что метод был вызван ровно один раз
    mockRepository.Verify(repo => repo.GetRecordCount(), Times.Once);
}

Почему Moq?

  • Простота: Легко осваивается и читается.
  • Строгая типизация: Настройки и проверки привязаны к сигнатурам методов интерфейса, что предотвращает ошибки.
  • Богатый функционал: Поддержка последовательных возвращаемых значений (ReturnsAsync, Throws), проверка аргументов (It.IsAny<int>(), It.Is<int>(x => x > 0)), кастомизация.

Альтернативные библиотеки:

  • NSubstitute: Имеет более лаконичный синтаксис (например, sub.GetCount().Returns(5)).
  • FakeItEasy: Известен простым API для создания заглушек (fakes).

Выбор между ними часто сводится к личным предпочтениям команды, но Moq остается стандартом де-факто для большинства проектов из-за зрелости и обширного сообщества.

Ответ 18+ 🔞

А, ну это ж классика, про моки в .NET! Слушай, тут всё просто, как три копейки. Если ты в .NET пишешь тесты и тебе нужно подменить какую-то зависимость — типа базы данных, внешнего API или ещё какой ебучий сервис, который на тестах грохается — то тебе нужна библиотека для создания моков.

И тут, блядь, король горы — это Moq. Её все знают, все используют, и синтаксис у неё такой, что даже твой пьяный коллега после корпоратива разберётся. Всё через точку настраивается, красиво.

Смотри, как это обычно выглядит. Допустим, у тебя есть сервис отчётов, который тыкается в репозиторий за данными.

// Интерфейс зависимости
public interface IDataRepository
{
    int GetRecordCount();
}

// Класс, который тестируем
public class ReportService
{
    private readonly IDataRepository _repository;
    public ReportService(IDataRepository repository) => _repository = repository;
    public bool HasData() => _repository.GetRecordCount() > 0;
}

И вот ты пишешь тест. Без Moq пришлось бы городить свой уёбищный класс-заглушку. А с Moq — красота!

// Юнит-тест с Moq
[Test]
public void HasData_ReturnsTrue_WhenRepositoryHasRecords()
{
    // 1. Arrange (Подготовка)
    var mockRepository = new Mock<IDataRepository>();
    // Вот тут магия: говоришь моку — слушай, когда вызовут GetRecordCount, верни пятёрку!
    mockRepository.Setup(repo => repo.GetRecordCount()).Returns(5);

    var service = new ReportService(mockRepository.Object);

    // 2. Act (Действие)
    bool result = service.HasData();

    // 3. Assert (Проверка)
    Assert.IsTrue(result);
    // А это, блядь, вообще мощь: можешь проверить, что метод вызвался ровно один раз, а не десять!
    mockRepository.Verify(repo => repo.GetRecordCount(), Times.Once);
}

Ну и почему все на Moq молятся?

  • Проще некуда: Разобраться — дело пяти минут.
  • Типы рулят: Всё строго типизировано, компилятор тебя предупредит, если ты какую-то хуйню сморозишь.
  • Функционала — овердохуища: Можно и исключения кидать через Throws, и значения по очереди возвращать, и аргументы проверять — типа, вызвался ли метод с числом больше нуля. В общем, полный карт-бланш.

Конечно, есть и другие ребята на районе:

  • NSubstitute — у них синтаксис ещё короче, типа sub.GetCount().Returns(5). Некоторые его обожают.
  • FakeItEasy — тоже известный пацан, у него свой подход к созданию фейков.

Но если честно, выбор между ними — это как спор между «Ашан» и «Лентой». Всё одно и то же, только полки по-разному стоят. Moq — это как тот проверенный «Ашан» у дома: может, не самый гламурный, но есть всё, что нужно, и народ туда ходит пачками. Его везде используют, у него сообщество огромное, так что с проблемой не останешься.

Короче, бери Moq, не прогадаешь. А там, глядишь, и до других библиотек руки дойдут, если очень припрет.