2

I'm trying to mock the return value of a MagicMock instance's function, but the result doesn't go as I expected:

>>> f = mock.MagicMock() # => <MagicMock id='139903823124048'>
>>> g = mock.MagicMock() # => <MagicMock id='139903823522512'>
>>> f.goo.return_value = g 
>>> g                    # => <MagicMock name='mock.goo()' id='139903823522512'>

Instance g hasn't changed but its name changes? And when I try:

>>> f.goo(1,2)
>>> g.zoo('a')
>>> f.goo(3,4)
>>> f.goo.assert_has_calls([call(1,2), call(3,4)])
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/home/lando/.local/lib/python2.7/site-packages/mock/mock.py", line 969, in assert_has_calls
    ), cause)
  File "/home/lando/.local/lib/python2.7/site-packages/six.py", line 737, in raise_from
    raise value
AssertionError: Calls not found.
Expected: [call(1, 2), call(3, 4)]
Actual: [call(1, 2), call().zoo('a'), call(3, 4)]

Why does g's call become a part of f.goo's call? Even:

>>> f.goo.call_args_list # => [call(1, 2), call(3, 4)]
Lan Do
  • 63
  • 6

1 Answers1

0

This behaviour not very intuitive, but is per expectation. See-

https://docs.python.org/3/library/unittest.mock.html#unittest.mock.Mock.assert_has_calls https://docs.python.org/3/library/unittest.mock.html#unittest.mock.Mock.mock_calls

The calls to the returned values are also tracked in the mock_calls.

Use the any_order flag.

  • So mock simply keeps track of all calls to itself as well as its method calls and attributes (according to method_calls), in a recursive way. And the assignment to return_value can be considered as an attachment to one of the "branches" of the hierarchical calls. That's what I understand. For the f.goo, the calls are not sequential so I can hardly use the any_order flag. Anw, thanks for answering. – Lan Do Mar 23 '18 at 07:02