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

Python unittest mock如何正确mock其他类的方法

问题根因

你的mock不生效是因为作用对象完全错了:

  • 你在测试代码中手动实例化的fruit = Fruit(),和Healthy.start()方法运行时内部通过Fruit()创建的实例是两个完全独立的对象
  • 你给外部手动创建的实例打start方法的mock,完全不会影响方法内部新生成的实例的执行逻辑
  • 另外你的测试代码调用healthy.start()时漏传了必填的arg位置参数,运行时会直接抛参数错误。
正确mock方案

仅使用unittest.mock内置的patch即可实现,不需要引入任何第三方工具,逻辑清晰易读。
核心规则:patch需要替换被测类所在模块中导入的外部依赖类,而不是外部依赖类本身的定义路径。比如你的Healthy类定义在jobs/healthy.py路径下,那么patch的目标路径就写jobs.healthy.Fruit,不要写jobs.fruit.Fruit。

推荐写法:装饰器形式(可读性最高)

from unittest.mock import MagicMock, patch
from jobs.healthy import Healthy

# patch装饰器的参数顺序和函数入参顺序是反向的,注意对应
@patch("jobs.healthy.Veggie")
@patch("jobs.healthy.Fruit")
def test_start_walk_fruit_logic(mock_fruit_cls, mock_veggie_cls):
    # 初始化被测对象,mock类自身的内部方法
    healthy = Healthy()
    healthy.start_connection = MagicMock(return_value=1)
    healthy.check = MagicMock(return_value=True)

    # 配置Fruit类mock的行为:实例化Fruit()时返回我们自定义的mock实例
    mock_fruit_ins = MagicMock()
    mock_fruit_ins.start.return_value = 0
    mock_fruit_cls.return_value = mock_fruit_ins

    # 执行被测方法,传入符合Fruit分支判断的参数
    test_arg = [1]  # 长度为1,满足分支条件
    result = healthy.start(test_arg)

    # 断言校验结果
    assert result == 1
    mock_fruit_ins.start.assert_called_once()
    mock_veggie_cls.assert_not_called()

备选写法:上下文管理器形式

如果只需要在局部代码段生效mock,可以用with上下文管理器包裹逻辑,避免装饰器传参:

from unittest.mock import MagicMock, patch
from jobs.healthy import Healthy

def test_start_walk_veggie_logic():
    healthy = Healthy()
    healthy.start_connection = MagicMock(return_value=1)
    healthy.check = MagicMock(return_value=False)

    with patch("jobs.healthy.Fruit") as mock_fruit_cls, patch("jobs.healthy.Veggie") as mock_veggie_cls:
        # 配置Veggie类mock行为
        mock_veggie_ins = MagicMock()
        mock_veggie_ins.update.return_value = None
        mock_veggie_cls.return_value = mock_veggie_ins

        # 传入走Veggie分支的参数
        test_arg = [1, 2]
        result = healthy.start(test_arg)

        # 断言校验
        assert result == 0
        mock_veggie_ins.update.assert_called_once()
        mock_fruit_cls.assert_not_called()

小提示:如果需要验证方法调用时的入参是否符合预期,可以直接用mock自带的assert_called_with方法校验,不需要额外写逻辑判断。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.01 00:04:09