Предположим, в проекте есть два пакета: some_package
и another_package
.
# 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
потому что в нем есть сетевой ввод- some_package.foo.bar
которого я хочу избежать.
Вот тест:
# 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
а не patched
. Я попытался отладить эту вещь, поставив точку останова IPDB в тесте. Когда я вручную импортирую some_package.foo.bar
после точки останова и вызова bar()
меня patched
.
На моем реальном проекте ситуация еще интереснее. Если я вызываю pytest в корне проекта, моя функция не исправляется, но когда я указываю в качестве аргумента tests/test_bar.py
- это работает.
Насколько я понимаю, это как-то связано с from some_package.foo import bar
. Если он выполняется до того, как происходит monkeypatching, то исправление не выполняется. Но на сжатой тестовой настройке из вышеприведенного примера установка исправлений не работает в обоих случаях.
И почему он работает в IPDB REPL после достижения точки останова?