单元测试时如何Mock Django views.py内调用的外部API POST请求
问题根源
Python unittest.mock 的核心规则是在哪里使用,就在哪里 patch,而非在对象定义的位置 patch。
你当前直接 patch 全局 requests.post 不生效的原因是:你的 views.py 中已经提前导入了 requests 模块,视图运行时调用的是 views 模块自己命名空间下绑定的 requests.post 方法,对全局 requests 的修改不会影响这个已经存在的引用,因此 mock 没有命中,还是会发起真实请求。
解决步骤
- 调整 patch 路径为你的
views.py中实际使用的requests引用路径
假设你的视图存放在myapp/views.py下,将 patch 装饰器的参数从'requests.post'修改为'myapp.views.requests.post' - 补全 mock 返回值的必要属性
你的视图代码中需要读取外部响应的status_code属性,仅设置ok=True会导致属性缺失报错,需要同步给 mock 返回值配置status_code。 - 修正测试代码的语法错误
原测试方法定义后缺失冒号,会触发语法报错。
修正后的测试代码示例
# 注意将路径替换为你自己项目中views.py对应的导入路径 @patch('myapp.views.requests.post') def test_external_api_call(self, mock_post): # 配置mock返回值,模拟外部接口返回200状态 mock_post.return_value.status_code = 200 mock_post.return_value.ok = True response = self.client.post(reverse('my-view'), { "dummy_key": "dummy_value" }, format='json') self.assertEqual(response.status_code, 200) # 可选补充校验:验证外部接口调用参数符合预期 mock_post.assert_called_once()
额外说明
如果你的 views.py 中是通过 from requests import post 的方式导入 post 方法,那么对应的 patch 路径需要调整为 'myapp.views.post',和实际导入的引用位置保持一致即可。
内容的提问来源于stack exchange,提问作者Adam
相关产品推荐
相关产品推荐

