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。
操作步骤:
- 安装motormock
pip install motormock
- 修改测试代码,用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
相关产品推荐
相关产品推荐

