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

FastAPI使用Pytest测试时报TypeError: dict对象不能用于await表达式

问题解决办法

问题根源

你业务代码中使用的是AsyncIOMotorClient异步Mongo驱动,所有collection.find_one()等操作返回的是协程对象,需要加await等待执行。但你测试用的mongomock是同步模拟库,它的find_one()直接返回结果字典,不是可等待对象,所以加了await就会触发TypeError: object dict can't be used in 'await' expression报错。
另外你测试代码中使用mongoengine的连接逻辑和业务中通过Depends(get_database)注入异步连接的逻辑完全不匹配,也是导致模拟不生效的原因之一。

解决方法

方案1:更换异步Mongo模拟库(最推荐)

使用专门适配motor异步驱动的模拟库motormock,它的接口和原生AsyncIOMotorClient完全一致,支持异步操作await。
操作步骤:

  1. 安装motormock
pip install motormock
  1. 修改测试代码,用FastAPI依赖覆盖功能替换数据库连接:
from fastapi.testclient import TestClient
from fastapi import status
from main import app
from motormock import MotorMockClient
# 导入你业务中注入数据库的依赖函数
from db.db_conn import get_database

client = TestClient(app)

# 初始化模拟异步Mongo客户端,插入测试数据
mock_client = MotorMockClient()
mock_client["CIA"]["Employees_Info"].insert_one({"name": "user_name","password": "week"})

# 覆盖原有的数据库依赖,所有接口注入的连接都会替换为模拟连接
app.dependency_overrides[get_database] = lambda: mock_client

def test_ping():
    response = client.get("/")
    assert response.status_code == status.HTTP_200_OK
    assert response.json() == {"message": "Conectado"}
   
def test_login():
    data = {"username":'user_name', 'password':'week'}
    response = client.post("/login", data=data)
    assert response.headers['Content-Type'] == 'application/json'
    assert response.status_code == status.HTTP_200_OK

注意:你之前插入的测试用户名为user_Name,登录传参是user_name,大小写不一致,测试时需要统一避免找不到用户。

方案2:封装mongomock同步方法为异步(不推荐,需要修改业务兼容逻辑)

如果不想换库,可以把mongomock的同步方法统一封装为异步协程,示例如下:

# 在db.py中新增兼容逻辑
import mongomock
async def mock_async_wrap(func, *args, **kwargs):
    return func(*args, **kwargs)

async def get_user_id(conn, user):
    collection = conn.CIA.get_collection("Employees_Info")
    # 测试环境下调用封装方法,生产环境走正常await
    if isinstance(conn, mongomock.MongoClient):
        user = await mock_async_wrap(collection.find_one, {'name':user},{"_id":1, "name":0, "password":0})
    else:
        user = await collection.find_one({'name':user},{"_id":1, "name":0, "password":0})
    if user:
        return user

内容的提问来源于stack exchange,提问作者Michael Zuñiga

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.05 22:18:04