测试使用Motor的FastAPI update_one接口时出现'object MagicMock can't be used in 'await' expression'断言错误
测试使用Motor的FastAPI update_one接口时出现'object MagicMock can't be used in 'await' expression'断言错误
嘿,我看了你的代码,这个报错主要是因为mock设置时机不对,而且没有正确模拟MongoDB客户端的层级结构,让我给你捋一捋怎么改:
问题根源
- mock设置太晚:你是先发送了请求
client.put(...),之后才给mock_motor_client.update_one赋值,这时候请求已经执行完了,代码里的await col.update_one根本没用到你设置的mock,自然会报错。 - mock层级不匹配:你的接口代码里是从
mongo_client["db"]["col"]拿到集合对象,再调用它的update_one方法,但你直接给mock_motor_client加了update_one,这和实际的调用路径完全对不上,代码执行时找不到能await的mock方法。
修正后的测试代码
@pytest.fixture(scope="session") async def mock_motor_client(): mock_client = AsyncMock() yield mock_client @pytest.mark.asyncio async def test_shield_disable_success(mock_motor_client): app = FastAPI() app.include_router(router) app.dependency_overrides[connection] = lambda: mock_motor_client # 1. 模拟MongoDB的层级:client -> db -> col mock_col = AsyncMock() # 设置update_one的返回值,匹配接口需要的matched_count和modified_count mock_col.update_one.return_value = AsyncMock(matched_count=1, modified_count=1) # 用__getitem__模拟通过["db"]获取数据库的行为,返回我们的mock集合 mock_motor_client.__getitem__.side_effect = lambda key: { "db": mock_col }[key] client = TestClient(app) # 2. 先把mock都设置好,再发送请求 response = client.put("/v2/shield?a=false") # 3. 断言结果 assert response.status_code == 200 # 额外可以断言update_one是否被正确调用(可选,但能确保接口逻辑正确) mock_col.update_one.assert_called_once_with( {"foo": "bar"}, {"$set": {"x": False}} )
关键调整点
- 提前设置mock:所有mock的配置都要放在发送请求之前,这样接口代码执行时才能用到正确的mock对象。
- 模拟层级结构:用
__getitem__来模拟通过键名获取数据库和集合的行为,让mongo_client["db"]["col"]能返回我们预先准备好的mock_col,这样调用col.update_one时就是在调用一个正确的AsyncMock方法,不会再出现await的错误。 - 可选的调用断言:加上
mock_col.update_one.assert_called_once_with(...)可以验证接口是否按照预期调用了数据库方法,让测试更严谨。
备注:内容来源于stack exchange,提问作者user30017120
相关产品推荐
相关产品推荐

