Python Mock问题:Mock方法外部依赖setup_logger时出错
问题根源
当测试文件执行from src.my_source import some_method时,Python会加载my_source.py模块,模块级代码logger = setup_logger()会立即执行真实的setup_logger函数。而原测试中的patch是在测试函数内部才生效,此时已经晚于模块加载的时机,真实函数被调用后触发了内部依赖的错误。
解决方案
必须在my_source模块被导入之前就完成setup_logger的Mock,以下是几种可行的实现方式:
方法1:使用pytest自动执行的Fixture
通过autouse=True的Fixture,在模块导入前启动patch:
from unittest.mock import patch import pytest @pytest.fixture(autouse=True) def mock_setup_logger(): with patch('src.my_source.setup_logger') as mock: # 给Mock设置返回值,模拟logger对象 mock.return_value = mock.Mock() yield mock # 此时导入模块,patch已经生效 from src.my_source import some_method def test_some_method(mock_setup_logger): some_method() # 可选:验证函数是否被调用 mock_setup_logger.assert_called_once()
方法2:在测试函数内部延迟导入模块
将模块导入放在测试函数内部,确保patch先启动:
from unittest.mock import patch import pytest @patch('src.my_source.setup_logger') def test_some_method(mock_setup_logger): mock_setup_logger.return_value = mock.Mock() # 延迟导入,此时patch已生效 from src.my_source import some_method some_method() mock_setup_logger.assert_called_once()
方法3:模块级Patch
在测试文件最顶部启动patch,覆盖整个测试模块的生命周期:
from unittest.mock import patch import pytest # 启动模块级patch patch_obj = patch('src.my_source.setup_logger') mock_setup_logger = patch_obj.start() mock_setup_logger.return_value = mock.Mock() # 导入模块,此时patch已生效 from src.my_source import some_method def test_some_method(): some_method() mock_setup_logger.assert_called_once() # 测试完成后停止patch def teardown_module(): patch_obj.stop()
内容的提问来源于stack exchange,提问作者deanavenger
相关产品推荐
相关产品推荐

