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

Python Click CLI单元测试:如何找到正确的函数Mock补丁字符串?

解决Click CLI工具Mock函数不生效的问题

核心原则:Mock的是函数被调用时所在模块的引用,而非函数定义的模块,以下根据你的代码结构给出具体方案。

先明确项目结构

假设你的项目目录如下:

your_project/
├── cli/
│   ├── __init__.py
│   ├── main.py
│   └── utils.py
└── tests/
    └── test.py

两种导入场景的正确Patch路径

场景1:main.py直接导入fn函数

如果cli/main.py的代码是这种形式:

# cli/main.py
import click
from cli.utils import fn  # 直接将fn导入main模块的命名空间

@click.command()
def main_cli():
    res = fn()
    click.echo(res)

此时必须Patch cli.main.fn,因为main.py已经把fn的引用复制到了自己的模块里,测试代码如下:

# tests/test.py
from click.testing import CliRunner
from unittest.mock import patch
from cli.main import main_cli

def test_mocked_fn():
    runner = CliRunner()
    with patch("cli.main.fn") as mock_fn:
        mock_fn.return_value = "Mocked结果"
        result = runner.invoke(main_cli)
        assert result.output.strip() == "Mocked结果"
        mock_fn.assert_called_once()

场景2:main.py通过utils模块调用fn

如果cli/main.py的代码是这种形式:

# cli/main.py
import click
import cli.utils  # 导入整个utils模块

@click.command()
def main_cli():
    res = cli.utils.fn()  # 通过模块调用fn
    click.echo(res)

此时需要Patch cli.utils.fn,测试代码如下:

# tests/test.py
from click.testing import CliRunner
from unittest.mock import patch
from cli.main import main_cli

def test_mocked_fn():
    runner = CliRunner()
    with patch("cli.utils.fn") as mock_fn:
        mock_fn.return_value = "Mocked结果"
        result = runner.invoke(main_cli)
        assert result.output.strip() == "Mocked结果"
        mock_fn.assert_called_once()

为什么之前的Patch不生效

你之前可能错误地Patch了函数定义的模块(比如场景1里Patch cli.utils.fn),但此时main.py已经持有了fn的独立引用,Mock原模块的函数不会影响到main.py里已经导入的副本。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.09 12:03:23