33

mock(http://mock.readthedocs.org/en/latest/index.html) is a great tool in python for unit test. It can conveniently mock a method or class or dict.But I encountered a problem which I couldn't find a straightforward way to deal with by mock.

This is the function to be tested:

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()

argument responses is a dict like object which has some other attributes(such as redundantErrorResponses) except dict inherent features. Now I want to construct a mock responses to let id in responsesto be True and id in responses.redundantErrorResponses to be False. This is what I do:

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 = {}

But error occurred:

function_to_be_tested(pole_id, mock_responses)

>>30 not exist

So how can I construct a MagicMock object meanwhile can iterate like a dict or how can I construct a dict meanwhile support MagicMock features(add attribute freely)?

lengxuehx
  • 1,500
  • 1
  • 18
  • 25
  • Should it be ```function_to_be_tested(pole_id, mock_responses)```? – wwii May 20 '15 at 04:22
  • 2
    For those who got here actually looking for how to mock a dict: You should check out [unittest.mock.patch.dict](https://docs.python.org/3/library/unittest.mock.html#unittest.mock.patch.dict). – seler Mar 31 '20 at 09:27

2 Answers2

56

Why mess around with __iter__? It seems to me that you want to mess with __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
mgilson
  • 300,191
  • 65
  • 633
  • 696
4

You can always just create some silly class to do the same thing.

In [94]: class MockResponses(dict):
   ....:     def redundantErrorResponses(self):
   ....:         return {}
Greg
  • 5,422
  • 1
  • 27
  • 32
  • I was really close to recommending the same thing :-). One note -- You don't even need a `property` here -- You could just have `redundantErrorResponses` as a class attribute since you're only going to make 1 instance anyway... – mgilson May 20 '15 at 04:26
  • Yes, this is my initial solution, but I just want to know " how construct a MagicMock object meanwhile can iterate like a dict ". @mgilson's answer is correct. – lengxuehx May 20 '15 at 04:38
  • 1
    That won't let you use methods such as `assert_called_with`. – gerrit Apr 08 '20 at 14:47