diff options
author | Gregory P. Smith <greg@krypto.org> | 2016-08-07 16:06:27 (GMT) |
---|---|---|
committer | Gregory P. Smith <greg@krypto.org> | 2016-08-07 16:06:27 (GMT) |
commit | d0d24fd1ae05a2aea84165cf0aae98f75a5203c8 (patch) | |
tree | 79cc2f86abbeb40149b52c3c2da4798387d57bb7 /Lib | |
parent | 3cc38327b636e81b079edb0fd206ec678276e83f (diff) | |
parent | 9854789efec0c707fff871b32b2833f32b078fb3 (diff) | |
download | cpython-d0d24fd1ae05a2aea84165cf0aae98f75a5203c8.zip cpython-d0d24fd1ae05a2aea84165cf0aae98f75a5203c8.tar.gz cpython-d0d24fd1ae05a2aea84165cf0aae98f75a5203c8.tar.bz2 |
Issue #26750: unittest.mock.create_autospec() now works properly for
subclasses of property() and other data descriptors. Removes the never
publicly used, never documented unittest.mock.DescriptorTypes tuple.
Diffstat (limited to 'Lib')
-rw-r--r-- | Lib/unittest/mock.py | 14 | ||||
-rw-r--r-- | Lib/unittest/test/testmock/testhelpers.py | 60 |
2 files changed, 44 insertions, 30 deletions
diff --git a/Lib/unittest/mock.py b/Lib/unittest/mock.py index 4f91c44..ed915d2 100644 --- a/Lib/unittest/mock.py +++ b/Lib/unittest/mock.py @@ -60,14 +60,10 @@ def _is_exception(obj): ) -class _slotted(object): - __slots__ = ['a'] - - -DescriptorTypes = ( - type(_slotted.a), - property, -) +def _is_data_descriptor(obj): + # Data descriptors are Properties, slots, getsets and C data members. + return ((hasattr(obj, '__set__') or hasattr(obj, '__del__')) and + hasattr(obj, '__get__')) def _get_signature_object(func, as_instance, eat_self): @@ -2153,7 +2149,7 @@ def create_autospec(spec, spec_set=False, instance=False, _parent=None, _kwargs.update(kwargs) Klass = MagicMock - if type(spec) in DescriptorTypes: + if _is_data_descriptor(spec): # descriptors don't have a spec # because we don't know what type they return _kwargs = {} diff --git a/Lib/unittest/test/testmock/testhelpers.py b/Lib/unittest/test/testmock/testhelpers.py index 1dbc0b6..3477634 100644 --- a/Lib/unittest/test/testmock/testhelpers.py +++ b/Lib/unittest/test/testmock/testhelpers.py @@ -802,35 +802,53 @@ class SpecSignatureTest(unittest.TestCase): a.f.assert_called_with(self=10) - def test_autospec_property(self): - class Foo(object): - @property - def foo(self): - return 3 + def test_autospec_data_descriptor(self): + class Descriptor(object): + def __init__(self, value): + self.value = value - foo = create_autospec(Foo) - mock_property = foo.foo + def __get__(self, obj, cls=None): + if obj is None: + return self + return self.value - # no spec on properties - self.assertIsInstance(mock_property, MagicMock) - mock_property(1, 2, 3) - mock_property.abc(4, 5, 6) - mock_property.assert_called_once_with(1, 2, 3) - mock_property.abc.assert_called_once_with(4, 5, 6) + def __set__(self, obj, value): + pass + class MyProperty(property): + pass - def test_autospec_slots(self): class Foo(object): - __slots__ = ['a'] + __slots__ = ['slot'] + + @property + def prop(self): + return 3 + + @MyProperty + def subprop(self): + return 4 + + desc = Descriptor(42) foo = create_autospec(Foo) - mock_slot = foo.a - # no spec on slots - mock_slot(1, 2, 3) - mock_slot.abc(4, 5, 6) - mock_slot.assert_called_once_with(1, 2, 3) - mock_slot.abc.assert_called_once_with(4, 5, 6) + def check_data_descriptor(mock_attr): + # Data descriptors don't have a spec. + self.assertIsInstance(mock_attr, MagicMock) + mock_attr(1, 2, 3) + mock_attr.abc(4, 5, 6) + mock_attr.assert_called_once_with(1, 2, 3) + mock_attr.abc.assert_called_once_with(4, 5, 6) + + # property + check_data_descriptor(foo.prop) + # property subclass + check_data_descriptor(foo.subprop) + # class __slot__ + check_data_descriptor(foo.slot) + # plain data descriptor + check_data_descriptor(foo.desc) class TestCallList(unittest.TestCase): |