使用 Mock 的常见场景:
- 模拟对象的类
- 用于测试中替代真实的对象
Mock和MagicMock的区别:
- Mock 类是 MagicMock 类的基类,它提供了一些基本的模拟功能,例如属性访问、方法调用等。
- MagicMock 类在Mock类的基础上增加了一些魔法方法,使得它可以更方便地模拟对象的行为。
(总结:大部分情况下,使用MagicMock就够了)
Mock VS MagicMock
模拟类
在下面的例子中我们有一个函数 some_function 实例化了 Foo 并调用该实例中的一个方法。 对 patch() 的调用会将类 Foo 替换为一个 mock。 Foo 实例是调用该 mock 的结果,所以它是通过修改 return_value 来配置的。
def some_function():
instance = module.Foo()
return instance.method()
with patch('module.Foo') as mock_name:
instance = mock_name.return_value
instance.method.return_value = 'the result'
result = some_function()
assert result == 'the result'
对象上的方法调用的 mock
下面这个简单的 ProductionClass 具有一个 closer 方法。 如果它附带一个对象被调用那么它就会调用其中的 close。
class ProductionClass:
def closer(self, something):
something.close()
real = ProductionClass()
mock = Mock()
real.closer(mock)
mock.close.assert_called_with()# 断言something.close是否被模拟调用
return_value:设置返回值和属性
mock = Mock()
mock.method.return_value = 3
mock.method()
side_effect:通过 mock 引发异常
mock = Mock(side_effect=Exception('Boom!'))#用于异常分支代码的覆盖
断言与重置
assert_called()#被调用
assert_called_once()#被调用恰好一次
assert_called_with(*args, **kwargs)#向该调用传入了指定的参数
assert_called_once_with(*args, **kwargs)#被调用恰好一次,并且向该调用传入了指定的参数
assert_not_called()#从未被调用过
reset_mock:将在 mock 对象上重围所有的调用属性
mock = Mock()
mock.reset_mock()#以免改变mock对象的调用属性,对于其他代码造成影响
call_count:一个告诉你 mock 对象已被调用多少次的整数值,可用于断言调用次数
mock = Mock(return_value=None)
mock.call_count#输出为0
mock()
mock()
mock.call_count#输出为2,调用了2次
例子:
self.assertEqual(2, mock.call_count)#断言mock被调用了2次