unitest.mock: Using autospec=True conflicts with 'wraps'Â #75988
Copy link
Copy link
Closed
Labels
3.7 (EOL)end of lifeend of lifestdlibStandard Library Python modules in the Lib/ directoryStandard Library Python modules in the Lib/ directorytype-bugAn unexpected behavior, bug, or errorAn unexpected behavior, bug, or error
Description
| BPO | 31807 |
|---|---|
| Nosy | @rbtcollins, @ezio-melotti, @voidspace, @Lukas0907, @tirkarthi |
| Files |
Note: these values reflect the state of the issue at the time it was migrated and might not reflect the current state.
Show more details
GitHub fields:
assignee = None
closed_at = None
created_at = <Date 2017-10-18.00:48:15.176>
labels = ['3.7', 'type-bug', 'library']
title = "unitest.mock: Using autospec=True conflicts with 'wraps'"
updated_at = <Date 2019-12-02.08:29:10.129>
user = 'https://bugs.python.org/JohnVillalovos'bugs.python.org fields:
activity = <Date 2019-12-02.08:29:10.129>
actor = 'xtreak'
assignee = 'none'
closed = False
closed_date = None
closer = None
components = ['Library (Lib)']
creation = <Date 2017-10-18.00:48:15.176>
creator = 'John Villalovos'
dependencies = []
files = ['47267']
hgrepos = []
issue_num = 31807
keywords = ['patch']
message_count = 3.0
messages = ['304549', '306273', '352287']
nosy_count = 6.0
nosy_names = ['rbcollins', 'ezio.melotti', 'michael.foord', 'John Villalovos', 'Lukas Anzinger', 'xtreak']
pr_nums = []
priority = 'normal'
resolution = None
stage = None
status = 'open'
superseder = None
type = 'behavior'
url = 'https://bugs.python.org/issue31807'
versions = ['Python 3.6', 'Python 3.7']Linked PRs
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
3.7 (EOL)end of lifeend of lifestdlibStandard Library Python modules in the Lib/ directoryStandard Library Python modules in the Lib/ directorytype-bugAn unexpected behavior, bug, or errorAn unexpected behavior, bug, or error
Projects
- StatusShow more project fieldsDone
Activity
JohnVillalovos commentedon Oct 18, 2017
If have autospec=True, then no ValueError is raised. If autospec=False or not defined, then the ValueError is raised.
@mock.patch('__main__.wrapped_func', autospec=True, wraps=wrapped_func)
def main(mock_wrap):
[-]Using autospec=True conflicts with 'wraps'[/-][+]unitest.mock: Using autospec=True conflicts with 'wraps'[/+]Lukas0907 commentedon Nov 15, 2017
I can reproduce the problem and have analyzed it a bit. My use case is a bit different, I want to use autospec=True and wraps= so that I can mock unbound methods but return the result from the original method (see also https://docs.python.org/3/library/unittest.mock-examples.html#mocking-unbound-methods).
The problem in the mock code is that mock.return_value actually calls __get_return_value() which replaces the actual return value mock.DEFAULT (which is stored in self._mock_return_value) with a new child mock. When the mock is then called and _mock_call() is executed, the wrapped function is not executed because self._mock_return_value is not mock.DEFAULT anymore:
Since self._mock_return_value is not DEFAULT anymore it doesn't matter if the mock wraps something and it will instead just return a new mock.
I think that the side effect of the assignment to self.return_value in _setup_func() is not intentional, i.e. the child mock should actually be created only if there is an outside access to return_value, but not when it is just wrapped in a function. The assignment can be made side effect free by assigning the internal attribute _mock_return_value (see attached patch). This solves the problem for me.
I've attached a patch that fixes the problem and doesn't seem to introduce a regression (all unittest.mock tests pass).
If somebody is interested in getting this merged, I'm happy to provide a regression test and everything else that is needed to get this merged.
Cheers,
Lukas
Lukas0907 commentedon Sep 13, 2019
Hi,
I just wanted to ask what the status for this bug is.
I'm still interested in getting this merged and would be happy to help.
Lukas
e-gebes commentedon Jan 10, 2023
I ran into the same issue with methods like @Lukas0907 described it, on Python 3.10.
gh-75988: Fix issues with autospec ignoring wrapped object (#115223)
pythongh-75988: Fix issues with autospec ignoring wrapped object (pytâĶ
pythongh-75988: Fix issues with autospec ignoring wrapped object (pytâĶ
[3.12] gh-75988: Fix issues with autospec ignoring wrapped object (GHâĶ
[3.11] gh-75988: Fix issues with autospec ignoring wrapped object (GHâĶ
pythongh-75988: Fix issues with autospec ignoring wrapped object (pytâĶ
pythongh-75988: Fix issues with autospec ignoring wrapped object (pytâĶ