贝利信息

如何在 FastAPI 单元测试中正确 await HTTP 客户端请求

日期:2026-01-24 00:00 / 作者:碧海醫心

fastapi 测试中 `client.get()` 是同步方法,不能直接 `await`;需改用 `async with client.get(...) as response:` 语法获取异步响应对象,避免 `typeerror: object response can't be used in 'await' expression`。

在 FastAPI 的异步测试场景中(如使用 pytest-asyncio),一个常见误区是误将测试客户端的 .get() 方法当作协程函数调用。实际上,TestClient(来自 fastapi.testclient.TestClient)是完全同步的 HTTP 客户端,其所有方法(包括 .get(), .post() 等)均返回普通 Response 对象,不支持 await —— 这正是报错 TypeError: object Response can't be used in 'await' expression 的根本原因。

✅ 正确做法是:改用 httpx.AsyncClient 配合 @pytest.mark.asyncio,它才是为异步测试设计的官方推荐方案。TestClient 仅适用于同步测试;若需真正异步发起请求(例如测试中间件、流式响应或依赖事件循环的行为),必须切换到 AsyncClient。

以下是修正后的完整示例:

import pytest
from httpx import AsyncClient
from your_app.main import app  # 替换为你的 FastAPI 实例路径

@pytest.mark.asyncio
async def test_get_report(report_service, headers):
    """Test Report GET Response with true async client"""
    report_id = "sample-report-id"

    # Mock 服务层(确保其异步方法可被 await)
    report_service.query_db.query_fetchone = mock.AsyncMock(
        return_value={
            "id": "sample-id",
            "reportId": "sample-report-id",
            "reportName": "sample-report-name",
            "report": [],
        }
    )

    # 使用 httpx.AsyncClient(非 TestClient!)
    async with AsyncClient(app=app, base_url="http://test") as ac:
        response = await ac.get(f"/v2/report/{report_id}", headers=headers)

    assert response.status_code == 200
    assert response.json()["reportId"] == "sample-report-id"

⚠️ 注意事项:

总结:await 错误的本质是客户端类型不匹配。坚持「同步测试用 TestClient + 普通调用」,「异步测试用 AsyncClien

t + await」,即可彻底规避此类问题。