Python单元测试中Patch类未生效的问题求助
Python单元测试中Patch类未生效的问题求助
嗨,我之前也碰到过一模一样的问题,你的patch没生效主要是mock的目标和时机没搞对,我来帮你梳理清楚问题点和解决办法:
问题根源分析
你的src/get_foos.py在模块加载阶段就已经创建了全局的client实例(也就是client = Client1()这行代码),而你测试里的patch操作根本没影响到这个已经存在的实例:
- Patch路径错误:你写的
@patch(src.get_store.Client1)不仅路径大概率写错了(看起来应该是src.client.Client1?),更关键的是——你mock的是Client1的原模块,可get_foos.py在导入时就已经拿到了原类的引用,并且完成了实例化,所以这个mock完全碰不到已有的client对象。 - Mock对象设置错误:就算路径对了,你直接给
mock_client.get_foo.return_value赋值也没用——因为mock_client是类的mock,而get_foos里用的是早已创建好的实例,类mock的设置不会自动同步到已存在的实例上。 - 还有几个语法小坑:Python里断言用
==而不是===,函数定义末尾缺了冒号,patch的路径必须用字符串包裹。
两种实用解决办法
办法一:直接mock全局的client实例(推荐)
既然get_foos.py里已经有了全局的client实例,我们直接mock这个实例的get_foo方法就行,简单又直接:
from unittest.mock import patch from src.get_foos import get_foo, get_bar, client def test_get_foo(): with patch.object(client, 'get_foo') as mock_get_foo: mock_get_foo.return_value = 'myfoo' result = get_foo() assert result == 'myfoo' # 还能验证调用参数是否符合预期 mock_get_foo.assert_called_once_with("foo") def test_get_bar(): with patch.object(client, 'get_foo') as mock_get_foo: mock_get_foo.return_value = 'mybar' result = get_bar() assert result == 'mybar' mock_get_foo.assert_called_once_with("bar")
办法二:Patch类并重新加载模块
如果你想mock整个Client1类,那得确保在client实例创建前就完成patch,这时候可以通过重新加载模块来实现:
from unittest.mock import patch import importlib import src.get_foos @patch('src.get_foos.Client1') def test_get_foo(mock_client_class): # 配置mock实例的返回值 mock_client_instance = mock_client_class.return_value mock_client_instance.get_foo.return_value = 'myfoo' # 重新加载get_foos模块,让它用mock的类创建新实例 importlib.reload(src.get_foos) from src.get_foos import get_foo result = get_foo() assert result == 'myfoo' mock_client_instance.get_foo.assert_called_once_with("foo")
总结
你的核心问题就是模块加载时已经创建了真实实例,后续的类mock无法影响这个实例。第一种方法直接mock已有的实例最省心,完全不用修改业务代码,还能保留你全局实例的设计。
备注:内容来源于stack exchange,提问作者uday8486
相关产品推荐
相关产品推荐

