Ответ
Моки (Mock objects) — это объекты-заглушки, которые имитируют поведение реальных зависимостей (например, базы данных, внешних API, файловой системы) в unit-тестах. Они позволяют изолировать тестируемый код, проверять взаимодействие с зависимостями и инжектировать тестовые данные.
Ключевая цель: Проверить, что тестируемый модуль правильно вызывает методы своих зависимостей с ожидаемыми аргументами.
Пример на Python с библиотекой unittest.mock:
from unittest.mock import Mock, patch
import requests
def fetch_user_data(user_id):
# Эта функция зависит от внешнего API
response = requests.get(f"https://api.example.com/users/{user_id}")
return response.json() if response.status_code == 200 else None
# Тест с моком для requests.get
@patch('requests.get')
def test_fetch_user_data_success(mock_get):
# 1. Настраиваем мок: задаём возвращаемое значение
mock_response = Mock()
mock_response.status_code = 200
mock_response.json.return_value = {"id": 1, "name": "John"}
mock_get.return_value = mock_response
# 2. Выполняем тестируемую функцию
result = fetch_user_data(1)
# 3. Проверяем РЕЗУЛЬТАТ работы функции
assert result == {"id": 1, "name": "John"}
# 4. Проверяем ВЗАИМОДЕЙСТВИЕ: функция вызвала API с правильным URL
mock_get.assert_called_once_with("https://api.example.com/users/1")
Когда использовать моки:
- Unit-тестирование сервисов, которые зависят от медленных или нестабильных внешних систем (платёжные шлюзы, почтовые серверы).
- Тестирование исключительных сценариев, которые сложно воспроизвести в реальной системе (таймауты, ошибки 500).
- Верификация бизнес-логики, которая заключается в вызове определённых методов с конкретными параметрами.
Альтернативы и когда их выбирать:
- Стабы (Stubs) — только подменяют ответ, не проверяют взаимодействие. Используются, когда важен только результат.
- Фейки (Fakes) — упрощённая, но рабочая реализация зависимости (например, in-memory база данных). Подходят для интеграционных тестов.
- Реальные зависимости — используются в end-to-end (E2E) тестах для проверки всей системы в сборе.
Использование моков делает тесты быстрыми, стабильными и сфокусированными на конкретной единице кода.
Ответ 18+ 🔞
А, моки, блядь! Ну это ж классика, ёпта! Представь себе: сидишь ты пишешь код, а он, сука, тянет за собой кучу зависимостей — база данных, какой-нибудь внешний апишник, который отвечает раз в полгода, файловая система... И как его, блядь, протестировать-то? Ждать, пока этот левый сервис очухается? Да ну нахуй!
Вот тут-то и выходят на сцену моки (Mock objects), ебать мои старые костыли! Это такие подставные ублюдки, которые притворяются твоими настоящими зависимостями. Их задача — позволить тебе проверить твой код в изоляции, как будто он один в пустой комнате, и посмотреть, как он общается с этими самыми зависимостями. То есть, ты не просто смотришь, что функция вернула, а ты смотришь — а вызвала ли она вообще тот самый метод у соседа, и с теми ли аргументами, с которыми надо?
Смотри, как это выглядит на Python с unittest.mock:
from unittest.mock import Mock, patch
import requests
def fetch_user_data(user_id):
# Эта функция зависит от внешнего API
response = requests.get(f"https://api.example.com/users/{user_id}")
return response.json() if response.status_code == 200 else None
# Тест с моком для requests.get
@patch('requests.get')
def test_fetch_user_data_success(mock_get):
# 1. Настраиваем мок: задаём возвращаемое значение
mock_response = Mock()
mock_response.status_code = 200
mock_response.json.return_value = {"id": 1, "name": "John"}
mock_get.return_value = mock_response
# 2. Выполняем тестируемую функцию
result = fetch_user_data(1)
# 3. Проверяем РЕЗУЛЬТАТ работы функции
assert result == {"id": 1, "name": "John"}
# 4. Проверяем ВЗАИМОДЕЙСТВИЕ: функция вызвала API с правильным URL
mock_get.assert_called_once_with("https://api.example.com/users/1")
Видишь, в чём прикол? Мы не ждём ответа от реального сервера, который может лежать, тормозить или требовать токен. Мы подменили целый requests.get на свою куклу! И теперь можем проверить две вещи: что функция вернула правильные данные (шаг 3) и что она, сука, вообще позвонила по правильному адресу (шаг 4). Вот это второй пункт — это и есть сила моков, их взаимодействие.
Так когда же эту банду подставных лиц запускать?
- Юнит-тесты для сервисов, которые цепляются к медленным или нестабильным штукам (платежки, почта, смс-ки). Чтобы не ждать, пока они там свои дела сделают.
- Тестирование всяких пиздецов, которые в жизни случаются раз в пятилетку: таймауты, ошибки 500, отказ сети. С моком ты можешь создать эту ошибку по щелчку.
- Проверка бизнес-логики, которая по сути сводится к команде: "эй, сосед, вызови-ка свой метод
save()с вот этими данными". Мок это подтвердит или опровергнет.
А что, есть ещё кто-то?
Ну конечно, блядь! Не одними моками сыты:
- Стабы (Stubs) — это такие тихони. Они просто подменяют ответ, но им похуй, вызывали их или нет. Используешь, когда тебе важен только конечный результат, а не процесс.
- Фейки (Fakes) — это уже более навороченные ребята. У них внутри есть какая-никакая, но логика. Типа база данных в оперативке. Уже ближе к интеграционке.
- Настоящие зависимости — это для полного, блядь, погружения, в E2E-тестах. Когда надо проверить, что вся система от и до не развалится, как карточный домик.
Короче, моки — это твои лучшие друзья, когда надо сделать тесты быстрыми, стабильными и сфокусированными на одной конкретной детали, а не на всей вселенной вокруг. Без них — пиши пропало, будешь ждать ответа от внешнего апи, как дурак.