Python的unittest.mock模块中提供了两个主要的mock类,分别是Mock和MagicMock.
先看一下官方文档的定义:
MagicMock is a subclass of Mock with all the magic methods pre-created and ready to use.
其实已经很清楚了,MagicMock是Mock的子类,并且预先创建了全部magic method的mock。
也就是说,如果不需要mock magic method,两者使用起来并没有什么分别。来看个例子,先定义个类,里面只有一个成员方法,返回10倍的数值:
class Person: def get_10_times_value(self, value) return 10 * value
使用Mock类来mock掉这个成员方法:
def test_should_mock_get_10_times_value_with_Mock(self): p = Person() p.get_10_times_value = Mock(return_value=100) self.assertEqual(p.get_10_times_value(), 100)
使用MagicMock类来mock:
def test_should_mock_get_10_times_value_with_MagicMock(self): p = Person() p.get_10_times_value = MagicMock(return_value=100) self.assertEqual(p.get_10_times_value(), 100)
两者没有任何区别,都成功了mock了成员方法。
再看下两者的区别:
def test_should_raise_exception(self): m = Mock() list(m)TypeError: 'Mock' object is not iterable
因为使用Mock类时,默认不会创建__iter__这个magic method的mock,所以报错。
如果想mock __iter__这个方法,得自己去做,如下:
def test_should_mock_magic_method_with_Mock(self): m = Mock() m.__iter__ = Mock(return_value=iter([])) self.assertEqual(list(m), [])
而使用MagicMock类时默认就会mock掉所有的magic method,所以不需要自己mock,__iter__默认是空数组:
def test_should_mock_magic_method_with_MagicMock(self): m = MagicMock() self.assertEqual(list(m), [])
因为已经默认创建了magic method的mock,所以可以直接使用return_value属性来改变值:
def test_should_mock_magic_method_with_MagicMock(self): m = MagicMock() m.__iter__.return_value = [1, 2, 3] self.assertEqual(list(m), [1, 2, 3])
其他magic method类似。