使用pytest对依赖类实例的函数做单元测试的正确mock方法
你测试失败的核心原因有两点:
- 你额外对
some_module.SomeClass.some_method做了patch,这个全局mock的方法没有任何实现逻辑,调用后不会修改实例的some_attr属性,所以断言返回20必然失败。 - 测试逻辑不符合单元测试的隔离原则:你已经完成了
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
相关产品推荐
相关产品推荐

