使用pydantic.BaseModel时unittest.mock打补丁失败,求解决方案
解决Pydantic BaseModel子类实例方法打补丁的AttributeError问题
问题原因
Pydantic的BaseModel通过元类实现模型的字段验证、序列化等核心逻辑,子类的方法属于类属性而非实例属性。当使用patch.object(child_instance, 'method')时,unittest.mock会尝试在实例的__dict__中查找method属性,但该属性仅存在于类层面,因此抛出AttributeError。而普通类的实例允许动态添加属性覆盖类方法,所以不会出现这个问题。
解决方案
方案1:补丁子类的method方法(推荐)
直接针对Child类的method方法打补丁,所有Child实例都会自动使用mock方法:
from unittest.mock import AsyncMock, patch import pydantic class Parent(pydantic.BaseModel): async def method(self): raise NotImplementedError class Child(Parent): async def method(self): return False async def test_patching(): child_instance = Child() # 补丁Child类的method方法,而非实例 with patch.object(Child, 'method', new_callable=AsyncMock) as mock_method: mock_method.return_value = True assert await child_instance.method() is True
方案2:使用完整路径补丁方法
如果测试代码和模型不在同一模块,可以指定类方法的完整字符串路径:
# 假设Child类在my_module.models模块中 with patch('my_module.models.Child.method', new_callable=AsyncMock) as mock_method: child_instance = Child() mock_method.return_value = True assert await child_instance.method() is True
方案3:手动给实例绑定属性(不推荐)
如果必须针对单个实例打补丁,可以先手动将类方法绑定到实例,再执行补丁:
async def test_patching(): child_instance = Child() # 先将类方法绑定到实例,让实例拥有该属性 child_instance.method = child_instance.method with patch.object(child_instance, 'method', new_callable=AsyncMock) as mock_method: mock_method.return_value = True assert await child_instance.method() is True
内容的提问来源于stack exchange,提问作者Automatico
相关产品推荐
相关产品推荐

