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

Pytest结合pytest-mock实现依赖对象方法调用监听与传参校验

待测试代码
class Work:
    pass
class Engineer:
   def delegate(work: Work):
       print('Doing all the hard work')
class Manager:
   def __init__(self, engineer: Engineer):
       self.engineer = engineer

   def perform(work: Work):
       self.engineer.delegate(work)
测试需求

测试Manager类的perform()方法,验证engineer.delegate()方法是否被传入了正确的参数,预期测试逻辑伪代码如下:

# pseudo 
work = mock(Work)
engr = mock(Engineer)

mgr = spy(Manager)
mgr.perform(work)

verify(engr.delegate).times(1).capture(args)
assert args == work
pytest + pytest-mock 实现

首先注意:原代码中Engineer.delegate、Manager.perform作为实例方法漏写了首个self参数,直接运行会报错,需要先修正方法签名:

# 修正后的实例方法
class Engineer:
   def delegate(self, work: Work):
       print('Doing all the hard work')

class Manager:
   def __init__(self, engineer: Engineer):
       self.engineer = engineer

   def perform(self, work: Work):
       self.engineer.delegate(work)

测试代码直接使用pytest-mock自带的mocker fixture即可实现,不需要额外spy Manager对象——单元测试中被测类使用真实实例,仅替换其依赖为mock对象即可:

def test_manager_perform_pass_correct_param(mocker):
    # 创建mock依赖
    mock_work = mocker.Mock(spec=Work)
    mock_engineer = mocker.Mock(spec=Engineer)

    # 初始化真实被测对象,注入mock依赖
    manager = Manager(engineer=mock_engineer)

    # 执行被测逻辑
    manager.perform(mock_work)

    # 校验:delegate仅被调用1次,且入参为传入的work对象
    mock_engineer.delegate.assert_called_once_with(mock_work)

逻辑对应说明

  • mocker.Mock(spec=类) 对应伪代码中的mock(类),spec参数会限制mock对象仅存在原类的属性和方法,避免拼写错误导致测试无效
  • 不需要spy Manager:我们要验证的是Manager的真实执行逻辑,spy反而会替换真实逻辑,不符合单元测试要求
  • assert_called_once_with(目标参数) 同时覆盖了伪代码中的两个校验点:校验调用次数为1、校验入参与预期完全一致

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.27 06:54:32