Python中Mock和MagicMock的區別

Python的unittest.mock模塊中提供了兩個主要的mock類,分別是MockMagicMock.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相似。

相關文章
相關標籤/搜索