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

如何通过MockerFixture正确异步Mock Document类的find_one方法?

如何通过MockerFixture正确异步Mock Document类的find_one方法?

我来帮你梳理这个问题的原因和解决办法,你遇到的坑其实是异步方法mock的典型问题,咱们一步步来:

首先,先分析你之前的两个错误:

  1. patch FindInterface没生效:因为你代码里实际调用的是MyDocument.find_one(),如果MyDocument的find_one没有直接绑定到FindInterface的实现,或者你的patch路径不对,mock就不会覆盖到实际执行的方法,所以真实的find_one还是会返回None,触发你的错误。
  2. patch MyDocument报错“不能在await表达式中使用类型”:这是因为你直接把find_one替换成了get_my_document()的返回值(也就是一个MyDocument实例),而不是一个可调用的异步函数。await后面必须跟可await的对象(比如异步函数、协程对象),直接await一个实例肯定会报错。

正确的解决思路

因为find_one是异步方法,所以你的mock必须满足两个条件:

  • 指向正确的目标(也就是MyDocument类的find_one方法)
  • 是一个可await的对象(要么用AsyncMock,要么是自定义的异步函数)

具体实现方案

下面给你两种常用的正确写法:

方案一:用AsyncMock(推荐,最简洁)

pytest-mock的mocker已经集成了AsyncMock,可以直接用来创建异步方法的mock,指定它的返回值为你想要的文档实例:

# 先定义你的测试数据生成函数
def get_my_document():
    return MyDocument(name="test_doc", created=datetime.now(), desc="test description")

def test_your_endpoint(mocker):
    # 用AsyncMock来mock MyDocument的find_one方法,并指定返回值
    mock_find_one = mocker.patch.object(MyDocument, "find_one", mocker.AsyncMock(return_value=get_my_document()))
    
    # 执行你的endpoint测试逻辑,比如调用接口函数
    # response = await client.get("/your-endpoint")
    
    # 还可以验证mock是否被调用过
    mock_find_one.assert_awaited_once()

方案二:用自定义异步函数作为mock

如果你想自己控制mock的逻辑(比如根据不同参数返回不同结果),可以写一个异步函数来替换find_one:

async def mock_find_one(query=None):
    # 这里可以加自定义逻辑,比如根据查询参数返回不同内容
    if query and query.get("name") == "test_doc":
        return MyDocument(name="test_doc", created=datetime.now(), desc="test description")
    return None

def test_your_endpoint(mocker):
    # 把MyDocument的find_one替换成自定义的异步函数
    mocker.patch.object(MyDocument, "find_one", mock_find_one)
    
    # 执行测试逻辑...

额外提醒

如果你的find_one需要接收查询参数,还可以用side_effect来处理更复杂的场景,比如:

def test_with_query_params(mocker):
    mock_find_one = mocker.patch.object(MyDocument, "find_one", mocker.AsyncMock())
    # 根据不同的查询参数返回不同结果
    def mock_side_effect(query):
        if query == {"name": "test"}:
            return get_my_document()
        return None
    # 注意:side_effect如果是普通函数,AsyncMock会自动把它包装成异步的
    mock_find_one.side_effect = mock_side_effect
    
    # 执行测试...

这样就能正确mock异步的find_one方法,不会再出现找不到文档或者await报错的问题啦!

备注:内容来源于stack exchange,提问作者1llya

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.14 15:18:05