You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

FastAPI TestClient测试时如何避免触发接口内部真实第三方请求

问题原因

你当前mock不生效、真实触发外部请求的核心原因有两个:

  1. mock目标完全错误:你patch的是路由函数demo_api本身,而非路由内部调用的requests.post第三方请求方法。就算patch路径写对,也会直接跳过你写的所有接口逻辑,测试没有实际价值。
  2. 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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.30 07:12:28