#python #testing #pytest #monkeypatching
#python #тестирование #pytest #monkeypatching
Вопрос:
Я пробовал это:
def test_send_confirm_hit(monkeypatch):
hit = False
def called():
global hit
hit = True
monkeypatch.setattr("web.email.send_confirm", called)
# ... some event that will cause web.email.send_confirm to be hit
assert hit # verify send_confirm was hit
Похоже, это работает, хотя я бы предпочел не использовать глобальную переменную. Каков наилучший способ сделать это?
Комментарии:
1. Используйте a
unittest.mock.Mock
и проверьте.assert_called()
метод.2. Я бы хотел избежать использования
unittest
3. Вам не нужно писать тесты unittest, вы можете использовать его с pytest.
4. Вы могли бы установить pypi.org/project/mock и используйте
from mock import MagicMock
, но это всего лишь бэкпорт для более старых версий python, а в более новых версиях он просто псевдонимы вunittest
любом случае… так что не делайте этого5. @L3viathan Это так полезно и открывает глаза! Я думал, что не могу смешивать
pytest
тесты с чем-либо из встроенногоunittest
мира.
Ответ №1:
Если вы используете «правильный» макет, он поставляется с .assert_called()
методом:
import unittest.mock
def test_send_confirm_hit(monkeypatch):
mock_send_confirm = unittest.mock.Mock()
monkeypatch.setattr("web.email.send_confirm", mock_send_confirm)
# ... some event that will cause web.email.send_confirm to be hit
mock_send_confirm.assert_called()
Комментарии:
1. Я понятия не имею, почему, но это не работает. Я добавил точку останова при запуске тестов в режиме отладки, и я знаю, что она вызывает этот метод….
2. Как вы импортируете
send_confirm
функцию, которую хотите протестировать? Если вы это сделаетеfrom web.email import send_confirm
, monkeypatching не будет работать, потому что функция уже имеет ссылку на realsend_confirm
. Что-то вродеfrom web import email; email.send_confirm()
will .3. это так странно, я не знал, что это такое! Спасибо за это!
Ответ №2:
Вы могли бы использовать макет вместо функции:
from unittest.mock import MagicMock
def test_send_confirm_hit(monkeypatch):
called = MagicMock()
monkeypatch.setattr("web.email.send_confirm", called)
# ... some event that will cause web.email.send_confirm to be hit
assert called.call_count == 1 # verify send_confirm was hit
Если вам действительно нужно выполнить какую-то пользовательскую логику, как вы бы сделали с функцией, вы можете добавить a side_effect
в макет:
def test_send_confirm_hit(monkeypatch):
def side_effect():
return 42
called = MagicMock(side_effect=side_effect)