Переместите from example import my_func
внутрь вашего with
в вашей функции тестирования. Также исправьте это, где это действительно происходит, other.get_value
. Это может быть все, что нужно.
Python кэширует модули в sys.modules
, поэтому код уровня модуля (например, определения функций) запускается только при первом импорте из в любом месте . Если это не первый раз, вы можете принудительно выполнить повторный импорт, используя importlib.reload()
или удалив соответствующий ключ в sys.modules
и импортировав снова.
Помните, что повторный импорт модуля может иметь побочные эффекты, и вы также можете захотеть повторно импортировать модуль после запуска теста, чтобы не мешать другим тестам. Если другой модуль использовал объекты, определенные в повторно импортированном модуле, они не просто исчезают и не могут быть обновлены так, как он ожидает. Например, повторный импорт модуля может создать второй экземпляр того, что должно было быть одиночным.
Еще один надежный подход - сохранить исходный импортированный объект модуля в другом месте, удалить из sys.modules
, повторно импортировать с исправленной версией на время теста, а затем вернуть исходный импорт в sys.modules
после тест. Вы можете сделать это с помощью импорта внутри контекста patch.dict()
на sys.modules
.
import mock
import sys
import pytest
@pytest.fixture
def mock_get_value():
with mock.patch(
"other.get_value",
autospec=True,
) as _mock, mock.patch.dict("sys.modules"):
sys.modules.pop("example", None)
yield _mock
def test_my_func(mock_get_value):
from example import my_func
assert my_func() == 'result'
Еще одна возможность - вызвать декоратор самостоятельно в тесте по исходной функции. Если декоратор использовал functools.wraps()
/ functools.update_wrapper()
, то оригинальная функция должна быть доступна как атрибут __wrapped__
. Это может быть недоступно в зависимости от того, как был реализован декоратор.