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

如何无需修改main.py调用路径即可Mock run函数?

问题:无需修改main.py调用路径,如何Mock指定函数?

原代码场景

main.py

from path.to.mod import run

def foo(args: str):
    run(args)

test.py

@patch("path.to.mod.run")
def verify_args(mock):
    foo("bar")
    mock.assert_called_once_with("bar")

上述代码无法Mock run 函数,断言会失败。但如果将main.py修改为直接通过模块路径调用的形式:

def foo(args: str):
    path.to.mod.run(args)

测试就能成功Mock。

现在需要解决的是:不修改main.py的调用写法,如何实现正确Mock?

错误尝试及报错

如果将test.py修改为以下写法:

from path.to.mod import run
@patch("run")
def verify_args(mock):
    foo("bar")
    mock.assert_called_once_with("bar")

会触发如下报错:

TypeError: Need a valid target to patch. You supplied: 'run'

解决方案

问题根源在于Python的导入机制:当main.py中使用from path.to.mod import run时,run会被作为独立引用存入main.py的全局命名空间,foo函数调用的是这个本地引用,而非原模块path.to.mod中的run。因此,我们需要Mock的是main.py里的run引用,而非原模块的run。

修改test.py的patch目标为main.run(若main.py不在当前测试模块的导入路径下,需替换为完整的模块路径,比如my_package.main.run):

from unittest.mock import patch
from main import foo

@patch("main.run")
def verify_args(mock_run):
    foo("bar")
    mock_run.assert_called_once_with("bar")

原理说明

  • 使用from X import Y导入时,Y会成为当前模块的本地变量,后续代码调用的是这个本地变量,而非原模块X中的Y。只有Mock这个本地变量,才能覆盖代码中的实际调用。
  • 之前的patch("path.to.mod.run")仅修改了原模块中的run,但main.py已持有导入时的旧引用,因此无法影响foo中的调用。
  • 直接patch("run")无效,是因为patch要求传入完整的模块路径,不能使用局部变量名。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.23 04:40:55