Предположим, что в проекте две упаковки: some_package
и another_package
.Pytest monkeypatch не работает на импортной функции
# some_package/foo.py:
def bar():
print('hello')
# another_package/function.py
from some_package.foo import bar
def call_bar():
# ... code ...
bar()
# ... code ...
Я хочу проверить another_package.function.call_bar
насмешливый из some_package.foo.bar
, потому что он имеет некоторую сеть I/O, я хочу, чтобы избежать.
Вот тест:
# tests/test_bar.py
from another_package.function import call_bar
def test_bar(monkeypatch):
monkeypatch.setattr('some_package.foo.bar', lambda: print('patched'))
call_bar()
assert True
К моему удивлению, он выводит hello
вместо mock
. Я попытался отладить эту вещь, поставив точку проверки ipdb в тесте. Когда я вручную импортирую some_package.foo.bar
после точки останова и звоню bar()
, я получаю patched
.
В моем реальном проекте ситуация еще более интересная. Если я вызываю pytest в корне проекта, моя функция не исправлена, но когда я укажу tests/test_bar.py
как аргумент - он работает.
Насколько я понимаю, это как-то связано с заявлением from some_package.foo import bar
. Если он выполняется до того, как происходит monkeypatching, то исправление не выполняется. Но на сконденсированной тестовой установке из приведенного выше примера исправление не работает в обоих случаях.
И почему он работает в IPDB REPL после достижения точки останова?
Это один из худших ошибок с помощью pytest - но, спасибо, что объяснил это. –
Когда вы говорите «use module.bar», можете ли вы представить пример кода? Я пробовал 'monkeypatch.setattr (модуль, 'bar', mock_obj)' и несколько других заклинаний без успеха. – skolsuper
Благодарим вас за ответ. Есть ли что-то трюк, чтобы быть уверенным, что любой импорт будет использовать насмешливый объект. Потому что пока это опасно, если, например, я пытаюсь высмеять orm-объект – Stavinsky