Skip to content

Commit 23ba96e

Browse files
[3.12] gh-90848: Fixed create_autospec ignoring configure_mock style 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 <46137868+infohash@users.noreply.github.com>
1 parent 238efbe commit 23ba96e

File tree

3 files changed

+26
-8
lines changed

3 files changed

+26
-8
lines changed

Lib/test/test_unittest/testmock/testmock.py

+13
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,19 @@ def f(): pass
104104
with self.assertRaises(TypeError):
105105
mock()
106106

107+
def test_create_autospec_should_be_configurable_by_kwargs(self):
108+
"""If kwargs are given to configure mock, the function must configure
109+
the parent mock during initialization."""
110+
mocked_result = 'mocked value'
111+
class_mock = create_autospec(spec=Something, **{
112+
'return_value.meth.side_effect': [ValueError, DEFAULT],
113+
'return_value.meth.return_value': mocked_result})
114+
with self.assertRaises(ValueError):
115+
class_mock().meth(a=None, b=None, c=None)
116+
self.assertEqual(class_mock().meth(a=None, b=None, c=None), mocked_result)
117+
# Only the parent mock should be configurable because the user will
118+
# pass kwargs with respect to the parent mock.
119+
self.assertEqual(class_mock().return_value.meth.side_effect, None)
107120

108121
def test_repr(self):
109122
mock = Mock(name='foo')

Lib/unittest/mock.py

+12-8
Original file line numberDiff line numberDiff line change
@@ -2757,8 +2757,8 @@ def create_autospec(spec, spec_set=False, instance=False, _parent=None,
27572757
if _parent is not None and not instance:
27582758
_parent._mock_children[_name] = mock
27592759

2760-
wrapped = kwargs.get('wraps')
2761-
2760+
# Pop wraps from kwargs because it must not be passed to configure_mock.
2761+
wrapped = kwargs.pop('wraps', None)
27622762
if is_type and not instance and 'return_value' not in kwargs:
27632763
mock.return_value = create_autospec(spec, spec_set, instance=True,
27642764
_name='()', _parent=mock,
@@ -2783,12 +2783,12 @@ def create_autospec(spec, spec_set=False, instance=False, _parent=None,
27832783
except AttributeError:
27842784
continue
27852785

2786-
kwargs = {'spec': original}
2786+
child_kwargs = {'spec': original}
27872787
# Wrap child attributes also.
27882788
if wrapped and hasattr(wrapped, entry):
2789-
kwargs.update(wraps=original)
2789+
child_kwargs.update(wraps=original)
27902790
if spec_set:
2791-
kwargs = {'spec_set': original}
2791+
child_kwargs = {'spec_set': original}
27922792

27932793
if not isinstance(original, FunctionTypes):
27942794
new = _SpecState(original, spec_set, mock, entry, instance)
@@ -2799,14 +2799,13 @@ def create_autospec(spec, spec_set=False, instance=False, _parent=None,
27992799
parent = mock.mock
28002800

28012801
skipfirst = _must_skip(spec, entry, is_type)
2802-
kwargs['_eat_self'] = skipfirst
2802+
child_kwargs['_eat_self'] = skipfirst
28032803
if iscoroutinefunction(original):
28042804
child_klass = AsyncMock
28052805
else:
28062806
child_klass = MagicMock
28072807
new = child_klass(parent=parent, name=entry, _new_name=entry,
2808-
_new_parent=parent,
2809-
**kwargs)
2808+
_new_parent=parent, **child_kwargs)
28102809
mock._mock_children[entry] = new
28112810
new.return_value = child_klass()
28122811
_check_signature(original, new, skipfirst=skipfirst)
@@ -2817,6 +2816,11 @@ def create_autospec(spec, spec_set=False, instance=False, _parent=None,
28172816
# setting as an instance attribute?
28182817
if isinstance(new, FunctionTypes):
28192818
setattr(mock, entry, new)
2819+
# kwargs are passed with respect to the parent mock so, they are not used
2820+
# for creating return_value of the parent mock. So, this condition
2821+
# should be true only for the parent mock if kwargs are given.
2822+
if _is_instance_mock(mock) and kwargs:
2823+
mock.configure_mock(**kwargs)
28202824

28212825
return mock
28222826

Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Fixed :func:`unittest.mock.create_autospec` to configure parent mock with keyword arguments.

0 commit comments

Comments
 (0)