如何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
相关产品推荐
相关产品推荐

