2014-02-18 56 views
0

我該如何嘲笑這樣的課程ablib.Pin?我該如何嘲笑關閉Pin的實例的屬性?我想說這應該像這樣工作:如何模擬像`module.Class`這樣的路徑?使用Python的模擬模塊?

mock = MagicMock()                
mock.Pin = MagicMock()            
mock.Pin.kernel_id = 'N21'              
mock.Pin.set_value.return_value = True           
mock.Pin.get_value.return_value = 3            

modules = { 
    'ablib': mock,              
    'ablib.Pin': mock.Pin,              
} 

patcher = patch.dict('sys.modules', modules)         
patcher.start()                   

當我創建一個PIN比如我和呼叫get_valueset_value我得到一個MockInstance代替True3

>>> p = Pin() 
>>> p.set_value(3) 
<MagicMock name='mock.Pin().set_value(3)' id='47965968'> 
>>> p.kernel_id 
<MagicMock name='mock.Pin().kernel_id' id='49231056'> 

當我直接打電話kernel_idPin我得到的結果,我需要。

>>> Pin.kernel_id 
'N21' 

如何嘲笑ablib.Pin的方式,我得到一個實例ablib.Pin()

回答

1

這裏是用最少的代碼修改工作版本我想要的值:

from unittest.mock import patch, MagicMock 

mock = MagicMock() 
mock.Pin().kernel_id = 'N21' 
mock.Pin().set_value.return_value = True 
mock.Pin().get_value.return_value = 3 

modules = { 
    'ablib': mock 
} 

patcher = patch.dict('sys.modules', modules) 
patcher.start() 

測試:

>>> import ablib 
>>> ablib.Pin 
<MagicMock name='mock.Pin' id='139917634188240'> 
>>> ablib.Pin 
<MagicMock name='mock.Pin' id='139917634188240'> 
>>> ablib.Pin() 
<MagicMock name='mock.Pin()' id='139917634233616'> 
>>> ablib.Pin() 
<MagicMock name='mock.Pin()' id='139917634233616'> 
>>> p = ablib.Pin() 
>>> p.set_value(3) 
True 
>>> p.kernel_id 
'N21' 

請注意,我已經刪除mock.Pin = MagicMock()和刪除mock.Pin從字典中。當您訪問現有的MagicMock屬性或調用它時,默認會創建新的MagicMock實例。下次執行該操作時將返回相同的實例。因此,不需要爲mock.Pin(對於Pin類),mock.Pin()(對於Pin實例)明確創建MagicMock,並將其註冊爲patch.dict()。只需註冊mock就足夠了。

感謝patch.dict()它即使在模塊ablib不存在時也能正常工作。我相信用patch()patch.object()是無法實現的。儘管如此,對於真正的單元測試,我使用patch()來模擬類和patch.object()來模擬某個特定測試或測試組的實例屬性。當我需要嘲笑整個模塊時,我還沒有遇到過這種情況,但我對單元測試和Python很陌生。