Библиотечный модуль:
# mod.py
def foo():
bar1("arg1")
bar2("arg2x", "arg2y")
def bar1(x):
pass
def bar2(x, y):
pass
Тестовый модуль:
# test_mod.py
from mod import foo
def test_foo(mocker):
mock = mocker.MagicMock()
mock.attach_mock(mocker.patch("mod.bar1"), "b1")
mock.attach_mock(mocker.patch("mod.bar2", autospec=True), "b2")
foo()
mock.assert_has_calls(
[
mocker.call.b1("arg1"),
mocker.call.b2("arg2x", "arg2y"),
]
)
The mocker
fixture is from pytest-mock
plugin. Execute the MCVE with python -m pytest
.
Этот тест не проходит для странныйпричины.
E AssertionError: Calls not found.
E Expected: [call.b1('arg1'), call.b2('arg2x', 'arg2y')]
E Actual: [call.b1('arg1')]
Без автоспек все работает. Нарушает ли использование autospec функцию attach_mock
? Как должен тест для foo
утверждать порядок и аргументы вызовов зависимостей bar1
и bar2
не теряя своих автоспец.?
@hoefling Что заставляет тебя так говорить? Это действительно макет, но автоспецификация делает макет более похожим на оригинал, чем обычно. Поместите 1/0
внутри тела bar2
, если хотите убедиться в этом.
На самом деле это была ошибка в Python. Это было исправлено в конце 2019 года, пропатченные версии:
Тест в исходном посте теперь проходит на исправленной версии. Нет бэкпорта для Python 3.6, который сейчас только безопасность, поэтому навсегда останется глючным. ?
Это соответствующие PR и ссылки на трекеры проблем:
бпо-21478: Функции Autospec должны распространять фиктивные вызовы родительским
бпо-21478: Записывайте вызовы родителя, когда объекты с автоматическим определением используются как дочерние с помощью attach_mock
бпо-38473: Обрабатывать автоматически заданные функции и методы, используемые с attach_mock
Нашивка Картикеяна Сингаравелана.
Хм, похоже,
mocker.patch("mod.bar2", autospec=True)
вообще не пропатчил функцию — можете проверить?