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

使用pytest对依赖类实例的函数做单元测试的正确mock方法

你测试失败的核心原因有两点:

  1. 你额外对some_module.SomeClass.some_method做了patch,这个全局mock的方法没有任何实现逻辑,调用后不会修改实例的some_attr属性,所以断言返回20必然失败。
  2. 测试逻辑不符合单元测试的隔离原则:你已经完成了SomeClass的单元测试,测试some_function的时候不需要再验证SomeClass内部的业务逻辑是否正确,只需要验证两者的交互流程符合预期即可。
正确实现

推荐写法(符合隔离原则)

这种写法只验证some_function的调用链路是否正确,完全不依赖SomeClass的实际实现,后续只要SomeClass的接口不变,即使内部逻辑调整,这个测试也不需要修改:

def test_some_function(mocker):
    # 模拟SomeClass类
    mock_some_class = mocker.patch("some_module.SomeClass")
    # 获取实例化后的mock对象
    mock_instance = mock_some_class.return_value

    # 执行被测函数
    result = some_function(10)

    # 验证SomeClass用入参10完成了实例化
    mock_some_class.assert_called_once_with(10)
    # 验证实例的some_method方法被调用了一次
    mock_instance.some_method.assert_called_once()
    # 验证函数返回的就是实例化后的对象
    assert result == mock_instance

模拟属性修改的写法

如果你确实需要模拟some_method执行后的属性变更效果,可以用下面的写法,不过这种场景并不推荐,因为SomeClass的内部逻辑本就应该在它自己的单元测试中覆盖:

def test_some_function(mocker):
    # 构造模拟实例,手动模拟some_method修改属性的行为
    mock_c = mocker.MagicMock()
    mock_c.some_attr = 10
    def update_attr():
        mock_c.some_attr = 20
    mock_c.some_method.side_effect = update_attr

    # 仅patch SomeClass的实例化返回即可,不要额外patch类的some_method
    mocker.patch("some_module.SomeClass", return_value=mock_c)

    res = some_function(10)
    assert res.some_attr == 20
    mock_c.some_method.assert_called_once()

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.01 11:54:03