FastAPI TestClient测试时如何避免触发接口内部真实第三方请求
问题原因
你当前mock不生效、真实触发外部请求的核心原因有两个:
- mock目标完全错误:你patch的是路由函数
demo_api本身,而非路由内部调用的requests.post第三方请求方法。就算patch路径写对,也会直接跳过你写的所有接口逻辑,测试没有实际价值。 - mock配置不符合接口逻辑:
resp.json()是方法调用,你之前直接给json属性赋值字典,就算mock到了正确位置也会报错。
另外你的路由代码本身有两个小问题:函数内使用的data变量没有定义,也没有给路由设置name参数,直接调用url_path_for('demo_api')会抛异常。
可行解决方案
你需要单独对接口内部的第三方requests.post调用做mock,具体实现步骤如下:
- 修正路由代码,补全缺失的请求参数获取逻辑,给路由添加name标识(如果要用
url_path_for的话):
from fastapi import APIRouter,Request import requests router = APIRouter() @router.post("/demo_router", name="demo_api") async def demo_api(request: Request): # 从入参中获取要转发给第三方接口的数据 data = await request.json() resp = requests.post("https://example.com", json=data) return {"resp_data": resp.json()}
- 修正测试代码的mock目标:按照unittest.mock的patch规则,你需要patch路由所在模块中引用的
requests.post对象(也就是src.endpoints.demo_module.requests.post),而不是全局的requests或者路由函数本身,同时正确配置mock返回值:
import unittest from fastapi.testclient import TestClient from unittest.mock import patch from main import app class DemoViewTestCase(unittest.TestCase): def test_demo_api_success(self): # 拦截路由模块内的requests.post调用,不会触发真实外部请求 with patch('src.endpoints.demo_module.requests.post') as mocked_post: # 配置mock响应 mock_resp = mocked_post.return_value mock_resp.status_code = 200 # json是可调用方法,返回值要绑定到json.return_value上 mock_resp.json.return_value = { "message": "request accepted", "success": True } client = TestClient(app) # 直接写接口路径更简洁,不容易出配置错误 response = client.post("/demo_router", json={"id": "BXBksk8920", "name": "Pjp"}) # 增加断言验证逻辑正确性 # 验证第三方接口被按预期参数调用 mocked_post.assert_called_once_with( "https://example.com", json={"id": "BXBksk8920", "name": "Pjp"} ) # 验证接口返回符合预期 self.assertEqual(response.status_code, 200) self.assertEqual( response.json(), {"resp_data": {"message": "request accepted", "success": True}} )
注意事项
- patch路径必须指向被测试模块(即写路由逻辑的py文件)中实际使用的对象引用,不要直接patch全局
requests.post,否则会出现mock不生效的问题。 - 不要mock你自己写的业务/路由逻辑,只需要mock不受你控制的外部依赖(比如第三方接口、数据库连接等),否则测试无法覆盖你自己写的代码逻辑,失去测试意义。
- 如果项目中大量使用requests调用第三方接口,也可以使用专门的requests mock库减少重复代码,不过用标准库的
unittest.mock已经可以完全实现需求,不需要额外安装依赖。
内容的提问来源于stack exchange,提问作者praveen jp
相关产品推荐
相关产品推荐

