classification
Title: unittest.mock: patched mocks do not propagate calls to parent when set via setattr
Type: behavior Stage: resolved
Components: Library (Lib) Versions: Python 3.8
process
Status: closed Resolution: not a bug
Dependencies: Superseder:
Assigned To: Nosy List: thinkingmachin6, xtreak
Priority: normal Keywords:

Created on 2020-07-14 19:03 by thinkingmachin6, last changed 2020-07-15 03:39 by xtreak. This issue is now closed.

Messages (2)
msg373654 - (view) Author: (thinkingmachin6) Date: 2020-07-14 19:03
I expected the following code to print True:

<pre>
import os
from unittest.mock import call, Mock, patch

parent = Mock()
parent.getenv = patch('os.getenv')
with parent.getenv:
    os.getenv('FOO', 'bar')
expected = [call.getenv('FOO', 'bar')]
print(expected, '==', parent.mock_calls, ':', expected == parent.mock_calls)
</pre>

It works fine if you replace the statement `parent.getenv = patch('os.getenv')` with:
<pre>
parent.getenv = patch('os.getenv', _mock_parent=parent,
                      _mock_new_parent=parent, _mock_new_name='getenv')
</pre>


Background:

I was trying to make assertions about a mocked call within a mocked context generator.

<pre>
# c.py
from . import a
from . import b
def func():
    with a.context('c'):
        b.operation()
</pre>
<pre>
# test_c.py
from package.c import func
from unittest.mock import Mock, call, patch
parent = Mock()
parent.context = patch('package.a.context')
parent.operation = patch('package.b.operation')
with parent.context, parent.operation:
    func()
assert parent.mock_calls == [
   call.context('c'),
   call.context().__enter__(),
   call.operation(),
   call.context().__exit__(None, None, None),
]
</pre>

in other words, to ensure the correct order of the __enter__/__exit__ calls relative to the actual operation. I have my workaround but it's very awkward looking.
msg373656 - (view) Author: (thinkingmachin6) Date: 2020-07-14 19:47
This appears to be a case of RTFM (https://docs.python.org/3/library/unittest.mock.html#attaching-mocks-as-attributes). For anybody that comes across this, the short answer is use `attach_mock()` instead of plain attribute-setting.
History
Date User Action Args
2020-07-15 03:39:20xtreaksetstatus: open -> closed
stage: resolved
2020-07-14 19:47:08thinkingmachin6setresolution: not a bug
messages: + msg373656
2020-07-14 19:07:39xtreaksetnosy: + xtreak
2020-07-14 19:03:59thinkingmachin6create