如何Mock Python类中通过setattr动态添加的对象方法?
问题原因
你遇到的报错本质上是两个问题导致的:
- 拼写错误:你patch的路径是
onleet.Onfleet.tasks.get,实际包名是onfleet,拼写错误会直接导致找不到目标对象 - 动态属性的特性:
tasks不是Onfleet类的固有属性,只有当类实例化执行__init__方法里的_initialize_resources时,才会通过setattr动态绑定到实例上,直接patch类的tasks属性自然找不到目标。
可行解决方案
方案1:完全Mock Onfleet类(最通用,适合绝大多数场景)
直接Mock整个Onfleet类,自定义实例返回的tasks.get行为,不需要依赖原类的初始化逻辑:
from unittest.mock import patch, MagicMock # 你的被测函数 def get_task(id): from onfleet import Onfleet api = Onfleet() return api.tasks.get(id=id) def test_get_task(): mock_onfleet_cls = MagicMock() # 配置实例的tasks.get返回值 mock_onfleet_instance = mock_onfleet_cls.return_value mock_onfleet_instance.tasks.get.return_value = {"id": "test_123", "status": 1} with patch("onfleet.Onfleet", new=mock_onfleet_cls): result = get_task(id="test_123") # 验证调用参数正确 mock_onfleet_instance.tasks.get.assert_called_once_with(id="test_123") assert result["id"] == "test_123"
方案2:局部Mock,保留原类其他逻辑
如果你需要保留Onfleet类的其他原有逻辑,只替换tasks.get方法,可以patch_initialize_resources方法,在原生初始化完成后替换目标方法:
from unittest.mock import patch, MagicMock from onfleet import Onfleet def test_get_task_partial(): # 备份原初始化方法 original_init_res = Onfleet._initialize_resources def patched_init_res(self, session): # 先执行原生初始化,生成所有端点属性 original_init_res(self, session) # 仅替换tasks.get为mock对象 self.tasks.get = MagicMock(return_value={}) with patch.object(Onfleet, "_initialize_resources", new=patched_init_res): api = Onfleet(api_key="test_key") result = api.tasks.get(id="test_123") api.tasks.get.assert_called_once_with(id="test_123")
内容的提问来源于stack exchange,提问作者bdoubleu
相关产品推荐
相关产品推荐

