Что такое Mock в контексте тестирования?

«Что такое Mock в контексте тестирования?» — вопрос из категории Тестирование, который задают на 25% собеседований C# Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Mock (Мок) — это объект-заглушка, который в тестах заменяет реальную зависимость. Его основная цель — изолировать тестируемый модуль, контролировать поведение зависимостей и проверять взаимодействие с ними (какие методы были вызваны, с какими аргументами и сколько раз).

Зачем это нужно?

  • Изоляция: Тестируете только логику конкретного класса, а не работу базы данных, внешнего API или файловой системы.
  • Контроль: Можете легко смоделировать любые сценарии — успешное выполнение, ошибки, долгие ответы.
  • Верификация: Убедиться, что ваш код корректно взаимодействует с другими компонентами.

Пример на C# с библиотекой Moq:

// Интерфейс зависимости (например, репозиторий)
public interface IUserRepository
{
    User GetById(int id);
    void Save(User user);
}

// Класс, который мы тестируем (сервис)
public class UserService
{
    private readonly IUserRepository _repository;
    public UserService(IUserRepository repository) => _repository = repository;

    public string ActivateUser(int userId)
    {
        var user = _repository.GetById(userId);
        user.IsActive = true;
        _repository.Save(user);
        return $"User {user.Name} activated.";
    }
}

// Сам тест с использованием Moq
[Test]
public void ActivateUser_ShouldActivateAndSaveUser()
{
    // 1. Arrange (Подготовка)
    var mockRepo = new Mock<IUserRepository>();
    var testUser = new User { Id = 1, Name = "Alice", IsActive = false };

    // Настраиваем мок: при вызове GetById с аргументом 1 вернуть testUser
    mockRepo.Setup(repo => repo.GetById(1)).Returns(testUser);

    var service = new UserService(mockRepo.Object);

    // 2. Act (Действие)
    var result = service.ActivateUser(1);

    // 3. Assert (Проверка)
    Assert.That(result, Is.EqualTo("User Alice activated."));
    Assert.That(testUser.IsActive, Is.True);
    // Верификация: метод Save был вызван ровно 1 раз с конкретным объектом user
    mockRepo.Verify(repo => repo.Save(testUser), Times.Once);
}

Ключевые методы Moq:

  • Setup() — задаёт поведение мока (что возвращать при вызове).
  • Returns() — определяет возвращаемое значение.
  • Verify() — проверяет, был ли вызов метода с ожидаемыми параметрами.