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

FastAPI异步测试报错:AttributeError: 'NoneType'对象无'send'属性

问题原因
  1. AsyncClient实例复用导致状态异常:如果AsyncClient被设置为module或class级别的pytest fixture,第一个测试结束后客户端连接会被自动关闭,第二个测试时实例内部的连接对象已变为None,调用请求方法时触发AttributeError: 'NoneType' object has no attribute 'send'。
  2. 数据库会话未做测试隔离:测试间未回滚/关闭数据库会话,导致连接池耗尽或会话状态污染,间接影响AsyncClient的请求处理流程。
解决方法

1. 配置Function级别的AsyncClient Fixture

强制每个测试用例生成全新的AsyncClient实例,彻底避免状态复用:

import pytest
from httpx import AsyncClient
from main import app

@pytest.fixture(scope="function")  # 核心:每个测试都创建新客户端
async def async_client():
    async with AsyncClient(app=app, base_url="http://test") as client:
        yield client

2. 实现数据库会话的测试隔离

每个测试后回滚数据并关闭会话,防止连接泄露和数据污染:

from sqlalchemy.ext.asyncio import AsyncSession
from your_db_module import async_session_factory

@pytest.fixture(scope="function")
async def db_session():
    session = async_session_factory()
    try:
        yield session
    finally:
        await session.rollback()  # 回滚测试数据,不影响其他用例
        await session.close()

3. 修复TestClient的异步用法(可选)

如果之前因用法错误放弃TestClient,可改用其官方异步API:

from fastapi.testclient import TestClient
from main import app

client = TestClient(app)

async def test_async_create_item():
    response = await client.async_post("/items/", json={"name": "test"})
    assert response.status_code == 200

4. 检查端点的数据库依赖注入

确保FastAPI端点使用请求级别的会话,而非全局实例:

from fastapi import Depends
from sqlalchemy.ext.asyncio import AsyncSession
from your_db_module import async_session_factory

async def get_db():
    async with async_session_factory() as session:
        yield session

@app.post("/items/")
async def create_item(item: Item, db: AsyncSession = Depends(get_db)):
    # 业务逻辑实现
    pass
报错验证

若报错栈指向httpx内部的send方法,基本可确认是AsyncClient实例已被关闭。使用function级fixture后,每个测试都会重新初始化客户端,彻底解决状态无效问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.16 06:52:42