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

如何复用AsyncClient Fixture?FastAPI测试注入异常问题排查

解决FastAPI异步测试中Session级AsyncClient Fixture异常问题

错误原因分析

你遇到的AttributeError: 'async_generator' object has no attribute 'get'由两个核心问题导致:

  1. lifespan调用方式错误:FastAPI的lifespan是绑定应用实例的生命周期钩子,无需手动调用上下文管理器;且你定义的lifespan的yield没有返回值,导致传入AsyncClient的app参数为None。
  2. 缺少Session级事件循环:Session级异步Fixture需要配套的Session级事件循环,否则pytest无法正确解析Fixture返回值,将AsyncClient实例误识别为async_generator对象。

修正后的代码

from contextlib import asynccontextmanager
from fastapi import FastAPI
import asyncio
from httpx import AsyncClient
import pytest

@asynccontextmanager
async def lifespan(app: FastAPI):
    print("starting up")
    yield
    print("shutting down")

app = FastAPI(lifespan=lifespan)

@app.get("/hello")
async def hello():
    await asyncio.sleep(2)
    return {"hello": "world"}

# 定义Session级事件循环,保证异步Fixture跨用例复用
@pytest.fixture(scope="session")
def event_loop():
    loop = asyncio.get_event_loop_policy().new_event_loop()
    yield loop
    loop.close()

# 修正后的Session级AsyncClient Fixture
@pytest.fixture(scope="session")
async def client():
    # 直接传入app实例,FastAPI自动处理lifespan生命周期
    async with AsyncClient(app=app, base_url="http://testserver") as client:
        yield client

@pytest.mark.asyncio
async def test_hello(client):
    response = await client.get("/hello")
    assert response.json() == {"hello": "world"}

关键修正点

  • 移除手动调用lifespan:AsyncClient加载app实例时,FastAPI会自动触发lifespan的启动和关闭逻辑,无需手动管理。
  • 添加Session级事件循环:确保Session内所有异步测试共用同一个事件循环,保证Session级Fixture的正常复用。
  • 简化Fixture逻辑:直接在AsyncClient的上下文管理器中yield实例,避免嵌套上下文导致的解析异常。

验证运行

执行pytest后,控制台会输出:

starting up
.
shutting down

测试用例会正常通过,且lifespan仅在Session启动和关闭时各执行一次,实现了Fixture的Session级复用。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.03 06:40:24