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

如何测试含内部逻辑的FastAPI POST接口?解决422报错问题

FastAPI接口测试422错误修复方案

接口代码(main.py)

from retriever import get_filtered_data

@app.post(
        "/getApi",
          response_class=JSONResponse,
          tags=["Some tags"],
          description="Some description"
        )
async def get_json_api(request: Basemodel,
                            params: Params = Depends()) -> Page:
    
    try:
        response = get_filtered_data('param_1',
                                    request=request)

        return paginate(response['items'],
                        additional_data={
                            "ABC": 123
                        },
                        params=params
                        )
    
    except Exception as exception:
        return HttpErrorResponse(data=f'ERROR details = {exception}',
                                 timestamp=datetime.now())

原测试用例代码

from fastapi.testclient import TestClient
from unittest.mock import patch, MagicMock, ANY

def test_get_json_property(self):
       mocked_response = requests.Response()
       
       with patch("requests.post", return_value=mocked_response) as mocked_request:
        response = self.client.post("/getApi",
                                    json={"in_filter": {"test_key": "test_value"}},
                                    headers={"content-type": "application/json"})

        mocked_request.return_value = {"items": {"test_key": "test_value"}}

        assert response.status_code == 200
        self.assertEqual(response.json(), mocked_response)

错误输出

{
  "type": "missing",
  "loc": ["response", "items"],
  "msg": "Field required",
  "input": "<HttpErrorResponse.HttpErrorResponse object at 0x000001FD7E0C17B0>"
},
{
  "type": "missing",
  "loc": ["response", "total"],
  "msg": "Field required",
  "input": "<HttpErrorResponse.HttpErrorResponse object at 0x000001FD7E0C17B0>"
},
{
  "type": "missing",
  "loc": ["response", "page"],
  "msg": "Field required",
  "input": "<HttpErrorResponse.HttpErrorResponse object at 0x000001FD7E0C17B0>"
},
{
  "type": "missing",
  "loc": ["response", "size"],
  "msg": "Field required",
  "input": "<HttpErrorResponse.HttpErrorResponse object at 0x000001FD7E0C17B0>"
},
{
  "type": "missing",
  "loc": ["response", "links"],
  "msg": "Field required",
  "input": "<HttpErrorResponse.HttpErrorResponse object at 0x000001FD7E0C17B0>"
}

问题原因

  1. Mock对象错误:测试中mock了requests.post,但接口实际依赖的是retriever.get_filtered_data,导致get_filtered_data执行真实逻辑时抛出异常,返回HttpErrorResponse。而接口声明的响应模型是Page,FastAPI校验返回结构不匹配,触发422错误。
  2. Mock返回值时机错误:在发送请求后才设置mocked_request.return_value,此时接口已经拿到初始的requests.Response()对象,该对象不是字典结构,执行response['items']时抛出异常。
  3. 断言逻辑错误:response.json()是接口返回的JSON字典,而mocked_response是requests.Response对象,两者类型和内容都不匹配,断言必然失败。

修复后的测试用例

from fastapi.testclient import TestClient
from unittest.mock import patch, MagicMock, ANY
from your_module import Page  # 导入Page模型

def test_get_json_property(self):
    # 模拟get_filtered_data的返回值,符合接口预期格式
    mock_filtered_data = {
        "items": [{"test_key": "test_value"}]  # items应为列表,适配paginate逻辑
    }
    
    # 正确mock依赖的get_filtered_data函数
    with patch("retriever.get_filtered_data", return_value=mock_filtered_data):
        # 发送请求,Params有默认值可省略,否则需补充参数
        response = self.client.post(
            "/getApi",
            json={"in_filter": {"test_key": "test_value"}},
            headers={"content-type": "application/json"}
        )
        
        # 断言状态码
        assert response.status_code == 200
        
        # 获取接口返回的JSON数据
        response_json = response.json()
        
        # 断言核心字段符合预期
        assert response_json["items"] == mock_filtered_data["items"]
        assert response_json["ABC"] == 123  # 验证附加数据
        # 按需断言分页字段,根据Params默认值调整
        assert response_json["page"] == 1
        assert response_json["size"] == 10  # 假设默认size为10

关键修改说明

  • 锁定Mock目标:直接mockretriever.get_filtered_data,避免绕开核心依赖层。
  • 提前设置返回值:在发送请求前定义好mock的返回结构,确保接口能正常进入paginate流程。
  • 匹配响应模型断言:按照Page模型的结构断言,验证分页字段和自定义附加数据,保证断言逻辑有效。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.22 19:42:33