Commit 656319e5 authored by Michael Foord's avatar Michael Foord

Make unittest.mock.create_autospec resilient against AttributeError on original object

parent 899ee613
...@@ -2044,10 +2044,14 @@ def create_autospec(spec, spec_set=False, instance=False, _parent=None, ...@@ -2044,10 +2044,14 @@ def create_autospec(spec, spec_set=False, instance=False, _parent=None,
# object to mock it so we would rather trigger a property than mock # object to mock it so we would rather trigger a property than mock
# the property descriptor. Likewise we want to mock out dynamically # the property descriptor. Likewise we want to mock out dynamically
# provided attributes. # provided attributes.
# XXXX what about attributes that raise exceptions on being fetched # XXXX what about attributes that raise exceptions other than
# AttributeError on being fetched?
# we could be resilient against it, or catch and propagate the # we could be resilient against it, or catch and propagate the
# exception when the attribute is fetched from the mock # exception when the attribute is fetched from the mock
original = getattr(spec, entry) try:
original = getattr(spec, entry)
except AttributeError:
continue
kwargs = {'spec': original} kwargs = {'spec': original}
if spec_set: if spec_set:
......
...@@ -651,6 +651,29 @@ class SpecSignatureTest(unittest.TestCase): ...@@ -651,6 +651,29 @@ class SpecSignatureTest(unittest.TestCase):
mock.f.assert_called_with(3, 4) mock.f.assert_called_with(3, 4)
def test_skip_attributeerrors(self):
class Raiser(object):
def __get__(self, obj, type=None):
if obj is None:
raise AttributeError('Can only be accessed via an instance')
class RaiserClass(object):
raiser = Raiser()
@staticmethod
def existing(a, b):
return a + b
s = create_autospec(RaiserClass)
self.assertRaises(TypeError, lambda x: s.existing(1, 2, 3))
s.existing(1, 2)
self.assertRaises(AttributeError, lambda: s.nonexisting)
# check we can fetch the raiser attribute and it has no spec
obj = s.raiser
obj.foo, obj.bar
def test_signature_class(self): def test_signature_class(self):
class Foo(object): class Foo(object):
def __init__(self, a, b=3): def __init__(self, a, b=3):
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment