如何让MagicMock表现得像个字典?

len*_*ehx 16 python mocking

mock(http://mock.readthedocs.org/en/latest/index.html)是python中用于单元测试的一个很好的工具.它可以方便地模拟一个方法或类或dict.But我遇到了一个问题,我找不到一个直接的方式来处理mock.

这是要测试的功能:

def function_to_be_tested(id, responses):
    if not id in responses:
        print '%s not exist'%pole_id
        return 

    if id in responses.redundantErrorResponses:
        print '%s is redundant'%pole_id
        return

    do_something()
Run Code Online (Sandbox Code Playgroud)

参数响应是一个类似于dict的对象,它具有一些其他属性(例如redundantErrorResponses),除了dict固有特性.现在我想构建一个模拟响应,让它id in responses成为True并id in responses.redundantErrorResponses成为False.这就是我做的:

pole_id = 30
pole_value = 100
pole_dic = {pole_id:pole_value}
mock_responses = MagicMock()
mock_responses.__getitem__.side_effect = lambda k: pole_dic[k]
mock_responses.__iter__.side_effect = iter(pole_dic)
mock_responses.redundantErrorResponses = {}
Run Code Online (Sandbox Code Playgroud)

但是发生了错误:

function_to_be_tested(pole_id, mock_responses)

>>30 not exist
Run Code Online (Sandbox Code Playgroud)

那么如何构建一个MagicMock对象同时可以像dict一样迭代,或者我如何构建一个dict同时支持MagicMock功能(自由添加属性)?

mgi*_*son 32

为什么搞乱__iter__?在我看来,你想搞砸__contains__:

>>> import mock
>>> m = mock.MagicMock()
>>> d = {'foo': 'bar'}
>>> m.__getitem__.side_effect = d.__getitem__
>>> m.__iter__.side_effect = d.__iter__
>>> m['foo']
'bar'
>>> 'foo' in m
False
>>> m.__contains__.side_effect = d.__contains__
>>> 'foo' in m
True
Run Code Online (Sandbox Code Playgroud)