Thanks to visit codestin.com
Credit goes to github.com

Skip to content

gh-90848: Fixed create_autospec ignoring configure_mock style kwargs #118163

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
May 2, 2024

Conversation

infohash
Copy link
Contributor

@infohash infohash commented Apr 22, 2024

Fix for:

Description

All mocks can be pre-configured with side_effect and return_value by passing them to kwargs which are consumed by the Mock class. But unittest.mock.create_autospec function is ignoring kwargs so, the user has to configure them later in the code after the initialization of the mock.

Test To Reproduce

from unittest import mock

import pytest


class Result:
    def get_result(self):
        pass


@pytest.mark.xfail
def test_result():
    class_mock = create_autospec(spec=Result, **{'return_value.get_result.side_effect': ValueError})
    with pytest.raises(ValueError):
        classmock().get_result()


def test_result_configure_later():
    class_mock = create_autospec(spec=Result)
    class_mock.return_value.get_result.side_effect = ValueError
    with pytest.raises(ValueError):
        classmock().get_result()

Details

This is the line 👇 which is consuming kwargs during the initialization of the mock:

cpython/Lib/unittest/mock.py

Lines 2774 to 2777 in 85f727c

mock = Klass(parent=_parent, _new_parent=_parent, _new_name=_new_name,
name=_name, **_kwargs)

Here 👇 we are overriding the return_value of the mock by creating a new mock on it but this is not the problem:

cpython/Lib/unittest/mock.py

Lines 2793 to 2797 in 85f727c

if is_type and not instance and 'return_value' not in kwargs:
mock.return_value = create_autospec(spec, spec_set, instance=True,
_name='()', _parent=mock,
wraps=wrapped)

As it is being called recursively 👆, the attributes of the specced object will also be mocked by creating child mocks 👇:

cpython/Lib/unittest/mock.py

Lines 2838 to 2841 in 85f727c

new = child_klass(parent=parent, name=entry, _new_name=entry,
_new_parent=parent,
**kwargs)
mock._mock_children[entry] = new

Then the child mocks are set on the recursive mock 👇:

cpython/Lib/unittest/mock.py

Lines 2849 to 2851 in 85f727c

if isinstance(new, FunctionTypes):
setattr(mock, entry, new)

This 👆 is the cause of the issue. We have set new child attribute mock which is not configured.

Fix Suggested by @tirkarthi

+    if _is_instance_mock(mock) and kwargs:
+        mock.configure_mock(**kwargs)

      return mock

Code Changes

  1. Added the above patch which will configure the parent mock only at the end because the user will pass kwargs with respect to the parent mock.
  2. Renamed local variable kwargs to child_kwargs because it was shadowing the name of the argument which is now being used to configure the parent mock.
  3. This 👇 should be popped because it will not be used again when configuring the parent mock at the end.
-    wrapped = kwargs.get('wraps')
+    # Pop wraps from kwargs because it must not be passed to configure_mock.
+    wrapped = kwargs.pop('wraps', None)

@infohash infohash requested a review from cjw296 April 23, 2024 08:52
@cjw296 cjw296 merged commit b28a333 into python:main May 2, 2024
34 checks passed
@cjw296 cjw296 added the needs backport to 3.12 only security fixes label May 2, 2024
@miss-islington-app
Copy link

Thanks @infohash for the PR, and @cjw296 for merging it 🌮🎉.. I'm working now to backport this PR to: 3.12.
🐍🍒⛏🤖

miss-islington pushed a commit to miss-islington/cpython that referenced this pull request May 2, 2024
@bedevere-app
Copy link

bedevere-app bot commented May 2, 2024

GH-118517 is a backport of this pull request to the 3.12 branch.

@bedevere-app bedevere-app bot removed the needs backport to 3.12 only security fixes label May 2, 2024
cjw296 pushed a commit that referenced this pull request May 2, 2024
…kwargs (GH-118163) (#118517)

gh-90848: Fixed create_autospec ignoring configure_mock style kwargs (GH-118163)
(cherry picked from commit b28a333)

Co-authored-by: infohash <[email protected]>
SonicField pushed a commit to SonicField/cpython that referenced this pull request May 8, 2024
@infohash infohash deleted the fix-issue-90848 branch June 19, 2024 11:21
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants