模拟或猴子修补导入时加载的缓慢加载资源

问题描述 投票:0回答:1

我有 1 个文件(从文件中)加载特定资源,需要一段时间才能加载。

我在 other 文件中有一个函数,它通过首先导入该资源来使用该资源。首次导入该资源时,它会加载并需要一些时间。

但是,当我测试需要该资源的函数时,我想传递另一个较小的资源。

不幸的是,我无法对

file1.py
file2.py
进行任何重大重构。有没有使用
pytest
的解决方案?我还没能让它工作。

文件1.py

def load_resource():
    print("Loading big resource...")
    return {"key": "big resource"}

resource = load_resource()

文件2.py

from file1 import resource

def my_func():
    return resource["key"]

测试.py

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'
python testing mocking pytest monkeypatching
1个回答
0
投票

如果不先导入全局函数,就无法修补该函数,因此我知道实现您所需的唯一方法是模拟整个模块。 这可以通过将

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
中移除,下次导入时加载真实模块。

当然,模拟模块内的任何其他属性或函数也将不起作用,因此如果您需要测试中该模块的更多功能,您可能需要进行更多模拟。

© www.soinside.com 2019 - 2024. All rights reserved.