[TIP] Error with Checking Calls to Multiple Mocks

John Papanastasiou johnnypapps at gmail.com
Mon May 20 04:20:09 PDT 2013


Julian,

Thank you so much for taking the time to review my code and tell me what
I've done wrong.

You're absolutely correct, initialising the ctx inside the loop means I can
make my assertions and validate the behaviour as expected.

Best regards,

John.




On Mon, May 20, 2013 at 12:04 PM, Julian Berman <julian at grayvines.com>wrote:

> Hi.
>
> Your issue is because you mutate ctx each time through the loop.
>
> Mock isn't going to try arbitrarily copying the arguments that are passed
> to your functions/mocks, so even though your mock was correctly called, by
> the time you make your assertion the dict has been mutated and now contains
> the form from the second time through the loop.
>
> Cheers,
> Julian
> On May 20, 2013 6:56 AM, "John Papanastasiou" <johnnypapps at gmail.com>
> wrote:
>
>> Apologies, the code I posted was missing an important print statement.
>>  I've attached the corrected script and more useful sample output:
>>
>> Regards,
>>
>> John.
>>
>>  ./nested_calls.py
>> ..
>> Mock: top_level: <mock.MagicMock object at 0x1005675d0>
>> Mock: nested: <mock.Mock object at 0x10059a990>
>> Call Args, top_level.handler.trigger: [(({'event': <mock.Mock object at
>> 0x10059a990>},), {})]
>> Mock: nested: <mock.Mock object at 0x10059a990>
>> Call Args, nested.handler.trigger: [(({'event': <mock.Mock object at
>> 0x10059a990>},), {})]
>>
>> F
>> ======================================================================
>> FAIL: test_top_level_and_extra (__main__.TestNestedCalls)
>> ----------------------------------------------------------------------
>> Traceback (most recent call last):
>>   File "./nested_calls.py", line 54, in test_top_level_and_extra
>>     top_level.handler.trigger.assert_called_once_with(ctx)
>> AssertionError: Expected: (({'event': <mock.MagicMock object at
>> 0x1005675d0>},), {})
>> Called with: (({'event': <mock.Mock object at 0x10059a990>},), {})
>>
>> ----------------------------------------------------------------------
>> Ran 3 tests in 0.059s
>>
>> FAILED (failures=1)
>>
>>
>> On Mon, May 20, 2013 at 11:52 AM, John Papanastasiou <
>> johnnypapps at gmail.com> wrote:
>>
>>> Hi,
>>>
>>> I believe I have found a problem with mock.call_args_list.  My
>>> understanding is that for a given mock, if the function you are testing
>>> makes multiple calls to a function on that mock, the call_args_list is set
>>> to a list of the successive argument lists for each call.
>>>
>>> The problem I have is that the call_args_list for one mock is being
>>> replaced with the call_args_list for a second mock that is being used in
>>> the same function under test.
>>>
>>> To demonstrate this, I have written a script which you can just run.
>>>
>>> I have an event object which has a property which may be set to a list
>>> of extra event objects.  Event objects have a property called handler which
>>> itself has a function trigger which called with a context (a dict with a
>>> key 'event' set to the event instance).
>>>
>>> The function i am trying to test triggers the handler on the top level
>>> event, then goes through each event in the list triggering their handlers.
>>>  To test this function, I am making assertions about the calls to the
>>> respective trigger functions.
>>>
>>> The attached code demonstrates that the call_args_list for the top_level
>>> event (the one being called first in the function) is set to the
>>> call_args_list for the extra event (the one being called second).
>>>
>>> The TestCase includes two unit tests which test the calls to the
>>> top_level event trigger and the nested event trigger independently and
>>> these pass.  The third unit test, test_top_level_and_extra prints out some
>>> information about the mocks involved and the call_args_lists.  This output
>>> demonstrates the error I am seeing.  I've pasted a sample output below.
>>>
>>> Is this a defect in the mock.call_args_list or have I misunderstood the
>>> documentation?
>>>
>>> Any help you can give is greatly appreciated.
>>>
>>> Regards,
>>>
>>> John.
>>>
>>> Sample Output:
>>>
>>> $ ./nested_calls.py
>>> ..
>>> Mock: top_level: <mock.MagicMock object at 0x100567590>
>>> Call Args, top_level.handler.trigger: [(({'event': <mock.Mock object at
>>> 0x10059a950>},), {})]
>>> Mock: nested: <mock.Mock object at 0x10059a950>
>>> Call Args, nested.handler.trigger: [(({'event': <mock.Mock object at
>>> 0x10059a950>},), {})]
>>>
>>> F
>>> ======================================================================
>>> FAIL: test_top_level_and_extra (__main__.TestNestedCalls)
>>> ----------------------------------------------------------------------
>>> Traceback (most recent call last):
>>>   File "./nested_calls.py", line 53, in test_top_level_and_extra
>>>     top_level.handler.trigger.assert_called_once_with(ctx)
>>> AssertionError: Expected: (({'event': <mock.MagicMock object at
>>> 0x100567590>},), {})
>>> Called with: (({'event': <mock.Mock object at 0x10059a950>},), {})
>>>
>>> ----------------------------------------------------------------------
>>> Ran 3 tests in 0.059s
>>>
>>> FAILED (failures=1)
>>>
>>>
>>>
>>>
>>
>> _______________________________________________
>> testing-in-python mailing list
>> testing-in-python at lists.idyll.org
>> http://lists.idyll.org/listinfo/testing-in-python
>>
>>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.idyll.org/pipermail/testing-in-python/attachments/20130520/087c456d/attachment.htm>


More information about the testing-in-python mailing list