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

