我有 1 个文件(从文件中)加载特定资源,需要一段时间才能加载。
我在 other 文件中有一个函数,它通过首先导入该资源来使用该资源。首次导入该资源时,它会加载并需要一些时间。
但是,当我测试需要该资源的函数时,我想传递另一个较小的资源。
不幸的是,我无法对
file1.py
或 file2.py
进行任何重大重构。有没有使用pytest
的解决方案?我还没能让它工作。
def load_resource():
print("Loading big resource...")
return {"key": "big resource"}
resource = load_resource()
from file1 import resource
def my_func():
return resource["key"]
import pytest
@pytest.fixture(autouse=True)
def mock_load_resource(monkeypatch):
def mock_resource():
return {'key': 'mocked_value'}
monkeypatch.setattr('file1', 'load_resource', mock_resource)
monkeypatch.setattr('file1', 'resource', mock_resource())
def test_my_function():
from file2 import my_func
result = my_func()
assert result == 'mocked_value'
如果不先导入全局函数,就无法修补该函数,因此我知道实现您所需的唯一方法是模拟整个模块。 这可以通过将
sys.modules
中的模块替换为您的模拟对象来完成:
from unittest.mock import Mock, patch
import pytest
@pytest.fixture(autouse=True)
def mock_load_resource():
def mock_resource():
return {'key': 'mocked_value'}
fake_file1 = Mock()
fake_file1.load_resource = mock_resource
fake_file1.resource = mock_resource()
with patch.dict('sys.modules', {'file1': fake_file1}):
yield
据我所知,
monkeypatch
没有允许这样做的方法,但你可以使用unittest.mock.patch.dict,如上所示。这确保了在测试期间,将加载模拟而不是真正的测试。测试完成后,将mock从sys.modules
中移除,下次导入时加载真实模块。
当然,模拟模块内的任何其他属性或函数也将不起作用,因此如果您需要测试中该模块的更多功能,您可能需要进行更多模拟。