如何像`module.Class`一样模拟路径?使用Python的Mock模块?

时间:2014-02-18 14:28:59

标签: python mocking

如何使用此路径ablib.Pin模拟课程?如何在Pin上模拟实例的属性?我会说它应该像这样工作:

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_id上致电Pin时,我得到了我需要的结果。

>>> Pin.kernel_id
'N21'

如何以我从实例ablib.Pin()获取我想要的值的方式模拟ablib.Pin

1 个答案:

答案 0 :(得分: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都很陌生。