Пример (pytest):
    def my_function(api):
      # Использует api
      return api.get_data()
    def test_my_function(mocker):
      mock_api = mocker.MagicMock()
      mock_api.get_data.return_value = "test_data"
      result = my_function(mock_api)
      assert result == "test_data"
      mock_api.get_data.assert_called_once()
  Цель: Изолировать функцию от внешних зависимостей, обеспечить предсказуемый результат теста.
При тестировании функций, взаимодействующих с внешними ресурсами (базы данных, API, файловая система), важно изолировать логику самой функции от нестабильности и непредсказуемости этих ресурсов. Мок-объекты (mocks) позволяют заменить реальные внешние зависимости их контролируемыми заменителями, что делает тесты более надежными, быстрыми и предсказуемыми.
Основные принципы использования мок-объектов:
Пример:
Предположим, у нас есть функция, которая получает данные пользователя из API:
  import requests
  def get_user_data(user_id):
    """Получает данные пользователя из API."""
    response = requests.get(f"https://api.example.com/users/{user_id}")
    response.raise_for_status()  # Вызывает исключение для кодов ошибок
    return response.json()
  Чтобы протестировать эту функцию, используя мок-объекты, можно воспользоваться библиотекой unittest.mock (встроена в Python) или pytest-mock (более удобная для использования с pytest):
Пример с unittest.mock:
  import unittest
  from unittest.mock import patch, MagicMock
  import requests
  # Функция, которую мы тестируем
  def get_user_data(user_id):
      response = requests.get(f"https://api.example.com/users/{user_id}")
      response.raise_for_status()
      return response.json()
  class TestGetUserData(unittest.TestCase):
      @patch('requests.get')
      def test_get_user_data_success(self, mock_get):
          # Настраиваем мок-объект
          mock_response = MagicMock()
          mock_response.json.return_value = {"id": 1, "name": "John Doe"}
          mock_response.raise_for_status.return_value = None  # Имитируем успешный ответ
          mock_get.return_value = mock_response
          # Вызываем функцию и проверяем результат
          user_data = get_user_data(1)
          self.assertEqual(user_data, {"id": 1, "name": "John Doe"})
          # Проверяем, что requests.get был вызван с правильным URL
          mock_get.assert_called_once_with("https://api.example.com/users/1")
      @patch('requests.get')
      def test_get_user_data_error(self, mock_get):
          # Настраиваем мок-объект для имитации ошибки
          mock_response = MagicMock()
          mock_response.raise_for_status.side_effect = requests.exceptions.HTTPError("Ошибка API")
          mock_get.return_value = mock_response
          # Проверяем, что функция вызывает исключение
          with self.assertRaises(requests.exceptions.HTTPError):
              get_user_data(1)
          # Проверяем, что requests.get был вызван с правильным URL
          mock_get.assert_called_once_with("https://api.example.com/users/1")
  if __name__ == '__main__':
      unittest.main()
  Пояснения:
@patch('requests.get'):  Этот декоратор заменяет реальную функцию requests.get мок-объектом.  Мок-объект передается в качестве аргумента в тестовую функцию (mock_get).MagicMock:  Универсальный мок-объект, который позволяет имитировать любые методы и атрибуты.mock_response.json.return_value = {"id": 1, "name": "John Doe"}:  Указывает, что при вызове mock_response.json() мок-объект должен вернуть словарь с данными пользователя.mock_response.raise_for_status.return_value = None:  Указывает, что при вызове mock_response.raise_for_status(),  который вызывается для проверки статуса ответа API,  мок должен вернуть None (т.е. имитирует успешный ответ 200 OK).mock_response.raise_for_status.side_effect = requests.exceptions.HTTPError("Ошибка API"):  Указывает, что при вызове mock_response.raise_for_status(), мок-объект должен вызвать исключение requests.exceptions.HTTPError, имитируя ошибку от API.mock_get.assert_called_once_with("https://api.example.com/users/1"):  Проверяет, что функция requests.get была вызвана ровно один раз и с ожидаемым URL.Преимущества использования мок-объектов:
Вывод:
Использование мок-объектов - важный навык для Python-разработчика. Это позволяет писать надежные, предсказуемые и быстрые тесты для функций, взаимодействующих с внешними ресурсами.