考慮下面的代碼(不是一個很好的設計,但是這一點):蟒蛇模擬:更換一個類的方法
class A(object):
def __init__(self,filepath):
self._access_file_system(filepath)
def get(self):
return self._result_dict
class B(object):
def __init__(self,filepath1,filepath2):
self._filepath1 = filepath1
self._filepath2 = filepath2
def foo(self):
a1 = A(self._filepath1).get()
a2 = A(self._filepath2).get()
return a1['result']==a2['result']
現在,如果我想測試B.foo()
,我需要模擬A
(如它訪問構造函數內的文件系統)。
編寫測試,將確保B.foo()
回報False
萬一a1.get()
和a2.get()
提供不同的價值,我也需要模擬B.get()
。
因此,測試功能或許應該如下所示:
import mock
mock_get = mock.MagicMock(side_effect=[{'result': 0}, {'result': 1}])
@mock.patch('__main__.A')
def test_foo(MockA):
b = B('/file1','/file2')
res = b.foo()
assert res
MockA.assert_any_call('/file1')
MockA.assert_any_call('/file2')
#Doesn't work -
#the assignment doesn't propagate into the objects instantiated inside foo()
#A.get = mock_get
#The assigned method propagates into the class definition,
#so it works - BUT WHY?!
a = A(None)
a.get = mock_get
b = B('/file1', '/file2')
res = b.foo()
assert not res
現在,奇怪的一點 - 因爲可以從代碼中的註釋中可以看出,如果我們指定mock_get
的類,它贏得不會傳播,但如果我們創建一個實例並分配給它,它就會傳播到該類的其他實例。
我想這種行爲與mock
的內部機制有關,所以對我來說理解它是非常重要的,以便正確使用這個庫以及它豐富的功能。
那麼,有沒有人有線索?