New We are sorting MAX channels into categories and territories. Read the news

✔️ Тест прошёл, но не потому что мок сработал



Классическая ловушка с моками в Python: тест зелёный, но реальный API всё равно вызывается. Вот как это происходит и как проверить что мок реально перехватил вызов.

Симптом

Тест на исключение при невалидной валюте проходит. Но в моке настроен ответ "result": "success" — который никогда не выбросит исключение. Как тест зелёный?

Реальный API вернул ошибку для несуществующей валюты «CTM». Мок вообще не сработал.

Как доказать что мок перехватил вызов

with pytest.raises(CurrencyConversionError):
convert_currency(
amount=Decimal("1.00"),
from_currency="CAD",
to_currency="CTM",
)

mock_get.assert_called_once() # если упал — мок не перехватил, бил реальный API

assert_called_once() — не опциональная проверка, а обязательная часть теста когда вы мокаете внешние вызовы.

Главное правило: патчить там где имя используется, не где определено

# модуль делает: import requests
# правильно:
mocker.patch("myapp.utils.currency.requests.get")

# если модуль делает: from requests import get
# то только так:
mocker.patch("myapp.utils.currency.get")
# requests.get здесь не перехватит ничего

Это самая частая причина почему мок «не работает».

Итоговый тест с pytest-mock

def test_bad_currency_raises(self, mocker):
mock_get = mocker.patch("myapp.utils.currency.requests.get")
mock_get.return_value.json.return_value = {
"result": "error",
"error-type": "unknown-code",
}

with pytest.raises(CurrencyConversionError):
convert_currency(Decimal("1.00"), "CAD", "CTM")

mock_get.assert_called_once()

Когда мок — не лучший инструмент

Если каждый тест завязан на конкретный import path — это тест реализации, не поведения. Альтернатива: адаптер-класс для внешнего вызова + fake-реализация + dependency injection. Тогда не нужно патчить вообще.
Views: 123
Open in MAX Report an inaccuracy

Report an inaccuracy

Describe what needs fixing. If you have a source, add a link.

You are leaving datool.ru

The link leads to an external website. datool.ru is not responsible for its content — check the address before entering passwords or payment details.

Redirecting in 10 s

Go