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

pytest使用mock patch拦截__init__失效 无法避免真实数据库连接

问题原因

你的mock逻辑不生效,核心是补丁替换时机晚于模块内实例化逻辑的执行时间:
当你在patch上下文内执行导入操作时,Python加载src.store模块的执行顺序是:

  1. 先为src.store创建空模块对象注册到sys.modules
  2. 逐行运行store.py内的代码:先完成Store类定义、绑定原始的__init__方法,紧接着就会执行模块底部的Store()实例化语句,直接触发真实的数据库连接
  3. 直到整个store.py代码全部执行完毕,patch才能拿到完整的src.store.Store类对象替换__init__方法,这时候实例化逻辑早就跑完了,补丁完全没赶上执行。

另外额外提一句:你业务代码里__init__方法的参数用了pass,这是Python保留关键字,实际运行会直接抛语法错误,建议改成password这类合法命名。

解决方案

方案1(推荐):消除导入阶段的副作用

这是最符合Python工程规范的解法:模块导入阶段不应该产生IO连接、全局实例化这类副作用,把顶层实例化逻辑放到脚本入口判断里即可。
修改project/src/store.py末尾代码:

# 只有直接运行当前脚本时才会执行实例化,导入模块时不会触发
if __name__ == "__main__":
    Store()

改完之后测试代码不需要额外做复杂mock,直接导入Store类即可测试静态方法,不会触发真实数据库连接。

方案2:不修改业务代码的前提下提前mock依赖

如果因为业务限制不能调整源码,可以在导入模块前,提前把触发连接的核心依赖mock掉,比直接mock__init__更稳定:
测试代码参考如下:

from unittest import mock
import sys

# 先给目标模块注册mock占位,避免导入时直接执行源码
sys.modules["src.store"] = mock.MagicMock()

with mock.patch("src.store.connection") as mock_connection:
    # 移除占位,真正执行模块导入
    del sys.modules["src.store"]
    from src.store import Store

    # 此时模块内执行Store()时调用的是mock后的connection,不会建立真实连接
    # 直接写测试用例即可
    def test_get_id():
        # 测试静态方法逻辑
        assert Store.get_id() == 预期结果

如果你确实需要替换__init__逻辑,只要把上面代码里patch的目标从src.store.connection换成src.store.Store.__init__即可,核心是要提前在导入前把补丁挂上,而不是等导入过程中再替换。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.27 14:36:14