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

