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

FastAPI+MongoDB pytest测试报NoneType无get_collection属性如何解决

问题原因

你遇到的报错核心是测试运行时MongoDB连接没有完成初始化,db.appDB 仍为None值,调用get_collection方法自然触发空指针异常。
具体触发原因:使用AsyncClient直接绑定FastAPI实例时,默认不会自动执行你注册的startup事件回调,导致connect_to_mongo函数没有被调用,数据库连接和appDB属性都没有完成赋值。而正常启动服务时uvicorn会自动触发startup事件,所以运行时不会报错。

解决方案

方案1:手动触发生命周期事件(快速修复)

直接在测试用例中手动执行数据库连接和关闭逻辑,修改测试代码如下:

import pytest
from httpx import AsyncClient
from fastapi import status
from fastapi_project.main import app
# 导入你定义的数据库连接/关闭函数
from fastapi_project.db import connect_to_mongo, close_mongo_connection

@pytest.mark.asyncio
async def test_successful_user_create():
    # 测试前手动初始化数据库连接
    await connect_to_mongo()
    async with AsyncClient(app=app, base_url="http://test") as ac:
        body = {            
            'username': 'test', 
            'email': 'test@test.com', 
            'hashed_password': 'password_test'            
        }
        # 绑定app后无需写完整请求地址,直接写接口路径即可
        res = await ac.post("/register", data=body)
    # 测试后手动关闭连接
    await close_mongo_connection()
    assert res.status_code == status.HTTP_201_CREATED

方案2:封装pytest fixture(更规范,适合多测试用例场景)

如果有多个测试用例都需要用到数据库连接,可以封装为pytest fixture统一处理生命周期,避免每个用例重复写连接/关闭逻辑:

import pytest
from httpx import AsyncClient
from fastapi import status
from fastapi_project.main import app
from fastapi_project.db import connect_to_mongo, close_mongo_connection, db

# fixture作用域可根据需求调整,function代表每个测试用例执行一次初始化/销毁
@pytest.fixture(scope="function")
async def test_client():
    # 测试前置:初始化数据库连接,建议测试环境单独使用测试库
    await connect_to_mongo()
    async with AsyncClient(app=app, base_url="http://test") as client:
        yield client
    # 测试后置:清空测试数据+关闭连接,避免数据污染
    await db.appDB.get_collection("users").delete_many({})
    await close_mongo_connection()

@pytest.mark.asyncio
async def test_successful_user_create(test_client):
    body = {            
        'username': 'test', 
        'email': 'test@test.com', 
        'hashed_password': 'password_test'            
    }
    res = await test_client.post("/register", data=body)
    assert res.status_code == status.HTTP_201_CREATED

额外注意项

  • 建议为测试环境单独配置MongoDB数据库,不要和开发/生产环境混用,避免测试数据影响正常业务数据。
  • 你粘贴的原始测试代码存在缩进错误:async with AsyncClient 行没有对应函数的缩进,若实际代码也是如此请先修正语法问题。
  • 测试接口请求无需写完整的服务地址,绑定app后直接传接口路径即可,也不需要对应端口和服务实际运行。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.02 10:24:00