如何mock预期接收Response对象的Pydantic BaseModel且不修改业务源码
报错根本原因
你开启的arbitrary_types_allowed配置仅允许Pydantic接收非标准类型的字段,并不会跳过isinstance类型校验。Pydantic依然会验证传入response字段的对象是否是Response类的实例,而默认构造的MagicMock对象无法通过这个校验,所以触发报错。
无侵入解决方案(无需修改业务代码)
- 方案1:创建Mock对象时指定
spec参数绑定Response类型(最推荐)
仅需要调整测试侧的Mock构造逻辑即可解决问题。给MagicMock加上spec=Response参数后,isinstance(your_mock, Response)会返回True,可以完全通过Pydantic的类型校验,同时还能约束Mock的属性/方法和原生Response类保持一致,避免测试通过但线上运行报错的情况。
示例代码:
from unittest.mock import MagicMock, patch # 导入业务代码中实际使用的Response类,比如requests.Response或者其他HTTP客户端的响应类 from requests import Response # 构造符合要求的Mock响应 mock_resp = MagicMock(spec=Response) # 按需给Mock添加业务逻辑需要的属性和方法 mock_resp.status_code = 200 mock_resp.json.return_value = {"code": 0, "data": {}} mock_resp.text = '{"code": 0, "data": {}}' # 如果是用patch装饰器/上下文管理器 mock请求方法,也可以直接在patch时指定spec @patch("你的业务模块路径.requests.get", spec=Response) def test_api_client(mock_get): mock_get.return_value = mock_resp # 执行测试逻辑即可,不会再触发类型校验报错
如果需要更严格的约束,防止测试中调用Response类不存在的方法,可以将spec替换为spec_set,只要调用原类不存在的属性/方法就会直接抛出错误,进一步提升测试可靠性。
- 方案2:临时Patch校验逻辑(仅特殊场景备用)
如果因为特殊限制不能修改Mock的构造逻辑,可以在测试运行时临时Patch对应字段的校验规则,该方案侵入性高于方案1,非必要不建议使用。
内容的提问来源于stack exchange,提问作者Symonen
相关产品推荐
相关产品推荐

