mirror of
https://github.com/python/cpython.git
synced 2025-08-11 04:19:06 +00:00
[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 b28a3339e4
)
Co-authored-by: infohash <46137868+infohash@users.noreply.github.com>
This commit is contained in:
parent
238efbecab
commit
23ba96e243
3 changed files with 26 additions and 8 deletions
|
@ -104,6 +104,19 @@ class MockTest(unittest.TestCase):
|
||||||
with self.assertRaises(TypeError):
|
with self.assertRaises(TypeError):
|
||||||
mock()
|
mock()
|
||||||
|
|
||||||
|
def test_create_autospec_should_be_configurable_by_kwargs(self):
|
||||||
|
"""If kwargs are given to configure mock, the function must configure
|
||||||
|
the parent mock during initialization."""
|
||||||
|
mocked_result = 'mocked value'
|
||||||
|
class_mock = create_autospec(spec=Something, **{
|
||||||
|
'return_value.meth.side_effect': [ValueError, DEFAULT],
|
||||||
|
'return_value.meth.return_value': mocked_result})
|
||||||
|
with self.assertRaises(ValueError):
|
||||||
|
class_mock().meth(a=None, b=None, c=None)
|
||||||
|
self.assertEqual(class_mock().meth(a=None, b=None, c=None), mocked_result)
|
||||||
|
# Only the parent mock should be configurable because the user will
|
||||||
|
# pass kwargs with respect to the parent mock.
|
||||||
|
self.assertEqual(class_mock().return_value.meth.side_effect, None)
|
||||||
|
|
||||||
def test_repr(self):
|
def test_repr(self):
|
||||||
mock = Mock(name='foo')
|
mock = Mock(name='foo')
|
||||||
|
|
|
@ -2757,8 +2757,8 @@ def create_autospec(spec, spec_set=False, instance=False, _parent=None,
|
||||||
if _parent is not None and not instance:
|
if _parent is not None and not instance:
|
||||||
_parent._mock_children[_name] = mock
|
_parent._mock_children[_name] = mock
|
||||||
|
|
||||||
wrapped = kwargs.get('wraps')
|
# Pop wraps from kwargs because it must not be passed to configure_mock.
|
||||||
|
wrapped = kwargs.pop('wraps', None)
|
||||||
if is_type and not instance and 'return_value' not in kwargs:
|
if is_type and not instance and 'return_value' not in kwargs:
|
||||||
mock.return_value = create_autospec(spec, spec_set, instance=True,
|
mock.return_value = create_autospec(spec, spec_set, instance=True,
|
||||||
_name='()', _parent=mock,
|
_name='()', _parent=mock,
|
||||||
|
@ -2783,12 +2783,12 @@ def create_autospec(spec, spec_set=False, instance=False, _parent=None,
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
kwargs = {'spec': original}
|
child_kwargs = {'spec': original}
|
||||||
# Wrap child attributes also.
|
# Wrap child attributes also.
|
||||||
if wrapped and hasattr(wrapped, entry):
|
if wrapped and hasattr(wrapped, entry):
|
||||||
kwargs.update(wraps=original)
|
child_kwargs.update(wraps=original)
|
||||||
if spec_set:
|
if spec_set:
|
||||||
kwargs = {'spec_set': original}
|
child_kwargs = {'spec_set': original}
|
||||||
|
|
||||||
if not isinstance(original, FunctionTypes):
|
if not isinstance(original, FunctionTypes):
|
||||||
new = _SpecState(original, spec_set, mock, entry, instance)
|
new = _SpecState(original, spec_set, mock, entry, instance)
|
||||||
|
@ -2799,14 +2799,13 @@ def create_autospec(spec, spec_set=False, instance=False, _parent=None,
|
||||||
parent = mock.mock
|
parent = mock.mock
|
||||||
|
|
||||||
skipfirst = _must_skip(spec, entry, is_type)
|
skipfirst = _must_skip(spec, entry, is_type)
|
||||||
kwargs['_eat_self'] = skipfirst
|
child_kwargs['_eat_self'] = skipfirst
|
||||||
if iscoroutinefunction(original):
|
if iscoroutinefunction(original):
|
||||||
child_klass = AsyncMock
|
child_klass = AsyncMock
|
||||||
else:
|
else:
|
||||||
child_klass = MagicMock
|
child_klass = MagicMock
|
||||||
new = child_klass(parent=parent, name=entry, _new_name=entry,
|
new = child_klass(parent=parent, name=entry, _new_name=entry,
|
||||||
_new_parent=parent,
|
_new_parent=parent, **child_kwargs)
|
||||||
**kwargs)
|
|
||||||
mock._mock_children[entry] = new
|
mock._mock_children[entry] = new
|
||||||
new.return_value = child_klass()
|
new.return_value = child_klass()
|
||||||
_check_signature(original, new, skipfirst=skipfirst)
|
_check_signature(original, new, skipfirst=skipfirst)
|
||||||
|
@ -2817,6 +2816,11 @@ def create_autospec(spec, spec_set=False, instance=False, _parent=None,
|
||||||
# setting as an instance attribute?
|
# setting as an instance attribute?
|
||||||
if isinstance(new, FunctionTypes):
|
if isinstance(new, FunctionTypes):
|
||||||
setattr(mock, entry, new)
|
setattr(mock, entry, new)
|
||||||
|
# kwargs are passed with respect to the parent mock so, they are not used
|
||||||
|
# for creating return_value of the parent mock. So, this condition
|
||||||
|
# should be true only for the parent mock if kwargs are given.
|
||||||
|
if _is_instance_mock(mock) and kwargs:
|
||||||
|
mock.configure_mock(**kwargs)
|
||||||
|
|
||||||
return mock
|
return mock
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
Fixed :func:`unittest.mock.create_autospec` to configure parent mock with keyword arguments.
|
Loading…
Add table
Add a link
Reference in a new issue