Моки

Что такое моки в pytest?

подробнее

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

Как включить моки в pytest?

подробнее

После установки плагина pytest-mock, появляется возможность использовать фикстуру mocker.
Пример: Если в app.py написано from utils import get_data, то патчить надо mocker.patch("app.get_data").

Основные операции

подробнее
  • Patch (Подмена)
    Заменяет функцию или объект на MagicMock.
    Пример:

      def test_api_call(mocker):
          # Подменяем метод get у библиотеки requests
          mock_get = mocker.patch("requests.get")
          # Задаем, что он должен вернуть
          mock_get.return_value.status_code = 200
          mock_get.return_value.json.return_value = {"id": 1}
            
          # Теперь реальный запрос в сеть не пойдет
          ...
    
  • Return Value (Результат) Что вернет мок при вызове: mock_obj.return_value = 42.
    • Side Effect (Побочный эффект)
      Позволяет выкинуть ошибку или возвращать разные значения при каждом вызове.
      Пример:
      # При вызове функции вылетит ошибка
      mocker.patch("os.remove", side_effect=PermissionError)
        
      # При первом вызове вернет 1, при втором 2
      mocker.patch("my_module.get_id", side_effect=[1, 2])
    
  • Spy (Шпионаж)
    Не подменяет функцию, но следит за ней: сколько раз вызвали, с какими аргументами.
    Пример:

      spy = mocker.spy(my_module, "my_func")
      my_module.my_func(1, 2)
      assert spy.called
      assert spy.call_count == 1
    

Проверки (Assertions для моков)

подробнее

После выполнения кода можно проверить, как дергали мок:

  • mock_obj.assert_called_once() — вызван ровно 1 раз.
  • mock_obj.assert_called_with(1, 2) — вызван именно с этими аргументами.
  • mock_obj.assert_not_called() — вообще не вызывался.