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

如何Mock单例实例方法?使用pytest拦截私有类单例的数据库调用

实现方案

不需要操作私有类__Foo,直接mock已经实例化并被导入的foo对象的对应方法即可,以下是两种常用实现方式:

方案1:Patch测试目标模块导入的foo方法

如果仅需要在测试bar函数时mock调用,直接patch bar所在模块导入的foo实例的call_database方法即可,示例如下:
假设bar函数存放在service/bar_module.py文件中,测试代码:

import pytest
from unittest.mock import AsyncMock
from service.bar_module import bar

async def test_bar(mocker):
    # 按照bar的导入路径patch对应foo实例的async方法
    mock_db_call = mocker.patch(
        "service.bar_module.foo.call_database",
        new_callable=AsyncMock
    )
    # 执行待测试函数
    await bar()
    # 验证方法被正确调用
    mock_db_call.assert_awaited_once()

方案2:全局Patch原模块导出的foo实例方法

如果多个业务模块都引用了foo实例,直接patch foo模块导出的实例方法即可,所有引用该实例的模块都会自动生效:

async def test_bar(mocker):
    # 直接patch foo模块导出的实例方法
    mock_db_call = mocker.patch(
        "foo.foo.call_database",
        new_callable=AsyncMock
    )
    await bar()
    mock_db_call.assert_awaited_once()

补充:直接Mock内部client方法

如果需要保留call_database的其他逻辑,仅mock内部的client请求,也可以直接访问实例的私有属性进行patch(Python私有属性仅为名称改写,并非完全不可访问):

async def test_bar(mocker):
    # 私有属性 __client 被改写为 _Foo__client
    mock_client_call = mocker.patch("foo.foo._Foo__client.do_thing")
    await bar()
    mock_client_call.assert_called_once()

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.26 03:24:04