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

如何对主要与3rd party APIs交互的Flask端点进行mock测试?

Flask中间层服务第三方API调用的Mock测试方案

核心思路是不用修改原有业务代码、也不需要重写端点,直接通过pytest-mock补丁替换你代码中调用第三方API的封装函数,既可以覆盖完整的路由参数校验、业务逻辑处理、返回值组装流程,又不会真实发起外部请求。

前置梳理:明确调用层级

你的代码中必然存在封装第三方API调用的独立函数/方法,示例结构如下:

# 第三方调用封装模块 例:third_parties/xxx_client.py
import requests
def query_xxx_service(user_id: str, req_data: dict) -> dict:
    resp = requests.post(
        "https://third-party-xxx.com/api/query",
        json=req_data,
        headers={"X-User-ID": user_id}
    )
    resp.raise_for_status()
    return resp.json()

# 路由模块调用上述封装 例:app/routes/xxx.py
from third_parties.xxx_client import query_xxx_service
@app.route("/api/v1/query-xxx", methods=["POST"])
def query_xxx_endpoint():
    # 路由层参数校验
    if not request.is_json:
        return {"error": "invalid request format"}, 400
    req_data = request.get_json()
    if "biz_id" not in req_data:
        return {"error": "missing biz_id"}, 400
    # 调用第三方API
    third_resp = query_xxx_service(request.headers.get("X-User-ID"), req_data)
    # 自定义返回值组装
    return {
        "code": 0,
        "data": {
            "biz_id": req_data["biz_id"],
            "result": third_resp["result_data"]
        }
    }

你只需要在测试中mockquery_xxx_service这个函数即可,不需要修改路由层的任何逻辑。

具体实现步骤

  1. 安装依赖
    pip install pytest-mock

  2. 编写测试用例

# 测试用例文件 例:test_xxx_endpoint.py
import requests

def test_normal_query_flow(mocker, client):
    # 1. 补丁替换路由中引用的第三方调用函数
    # 注意:patch路径是路由模块中import的路径,不是函数定义的原始路径,否则补丁不生效
    mock_query = mocker.patch("app.routes.xxx.query_xxx_service")
    # 2. 预设第三方API的返回值
    mock_query.return_value = {"result_data": "test_result", "extra_field": "xxx"}

    # 3. 正常调用测试客户端发起请求
    resp = client.post(
        "/api/v1/query-xxx",
        json={"biz_id": "12345"},
        headers={"X-User-ID": "u_67890"}
    )

    # 4. 断言路由逻辑符合预期
    assert resp.status_code == 200
    resp_data = resp.get_json()
    assert resp_data["code"] == 0
    assert resp_data["data"]["biz_id"] == "12345"
    assert resp_data["data"]["result"] == "test_result"

    # 5. 断言第三方调用参数符合预期,验证路由参数传递逻辑
    mock_query.assert_called_once_with("u_67890", {"biz_id": "12345"})

def test_third_api_error_handling(mocker, client):
    # 模拟第三方接口报错的场景,验证异常处理逻辑
    mock_query = mocker.patch("app.routes.xxx.query_xxx_service")
    mock_query.side_effect = requests.exceptions.HTTPError("500 Internal Server Error")

    resp = client.post(
        "/api/v1/query-xxx",
        json={"biz_id": "12345"},
        headers={"X-User-ID": "u_67890"}
    )

    assert resp.status_code == 503
    assert "third party service unavailable" in resp.get_json()["error"]

复用优化:封装为fixture减少重复代码

如果多个测试用例需要用到同一个第三方API的mock,可以在conftest.py中封装为pytest fixture全局复用:

# conftest.py
import pytest

@pytest.fixture
def mock_xxx_query(mocker):
    mock_func = mocker.patch("app.routes.xxx.query_xxx_service")
    mock_func.return_value = {"result_data": "default_test_result"}
    return mock_func

后续测试用例直接传入fixture即可使用,需要自定义返回值时单独修改即可:

def test_custom_response(mock_xxx_query, client):
    mock_xxx_query.return_value = {"result_data": "custom_value"}
    # 测试逻辑不变

内容的提问来源于stack exchange,提问作者JeffSpicoli

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.24 06:06:04