Ответ
Unit-тесты по определению должны быть быстрыми, детерминированными и изолированными. Вызов реальных внешних ресурсов (API, базы данных) нарушает эти принципы. Для изоляции тестов от сетевых вызовов используется техника мокинг (mocking).
Основной инструмент в стандартной библиотеке Python — unittest.mock
. Он позволяет заменить реальные объекты (функции, классы) на "заглушки" (моки) во время выполнения теста.
Пример с unittest.mock.patch
:
Предположим, есть функция, которая обращается к внешнему API:
# my_module.py
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()
Тест для этой функции будет выглядеть так:
# test_my_module.py
from unittest.mock import patch
from my_module import get_user_data
# @patch заменяет 'requests.get' на мок-объект
@patch('my_module.requests.get')
def test_get_user_data(mock_get):
# 1. Настраиваем мок: что он должен вернуть при вызове
mock_response_data = {'id': 1, 'name': 'John Doe'}
mock_get.return_value.status_code = 200
mock_get.return_value.json.return_value = mock_response_data
# 2. Вызываем тестируемую функцию
user_data = get_user_data(1)
# 3. Проверяем результат и то, что мок был вызван правильно
mock_get.assert_called_once_with('https://api.example.com/users/1')
assert user_data == mock_response_data
Преимущества этого подхода:
- Скорость: Тест выполняется мгновенно, без реальной сетевой задержки.
- Надежность: Результат теста не зависит от доступности API или состояния сети.
- Контроль: Можно легко эмулировать любые сценарии, включая ошибки (например,
status_code = 404
), для проверки обработки исключений.
Для более удобной работы с HTTP-запросами также популярна библиотека responses
.