Python的unittest.mock模塊中提供了兩個主要的mock類,分別是Mock和MagicMock.python
先看一下官方文檔的定義:數組
MagicMock is a subclass of Mock with all the magic methods pre-created and ready to use.code
其實已經很清楚了,MagicMock是Mock的子類,而且預先建立了所有magic method的mock。
也就是說,若是不須要mock magic method,二者使用起來並無什麼分別。文檔
來看個例子,先定義個類,裏面只有一個成員方法,返回10倍的數值:get
class Person: def get_10_times_value(self, value) return 10 * value
使用Mock類來mock掉這個成員方法:it
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:io
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了成員方法。class
再看下二者的區別:test
def test_should_raise_exception(self): m = Mock() list(m) TypeError: 'Mock' object is not iterable
由於使用Mock類時,默認不會建立__iter__這個magic method的mock,因此報錯。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相似。