gh-85934: Use getattr_static when adding mock spec (#22209)

Co-authored-by: Terry Jan Reedy <tjreedy@udel.edu>
Co-authored-by: Oleg Iarygin <oleg@arhadthedev.net>
This commit is contained in:
melanie witt 2023-05-23 16:10:34 -07:00 committed by GitHub
parent 6b1510cf11
commit 2e0931046d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 40 additions and 1 deletions

View File

@ -38,6 +38,17 @@ class Something(object):
def smeth(a, b, c, d=None): pass
class SomethingElse(object):
def __init__(self):
self._instance = None
@property
def instance(self):
if not self._instance:
self._instance = 'object'
return self._instance
class Typos():
autospect = None
auto_spec = None
@ -2293,6 +2304,26 @@ class MockTest(unittest.TestCase):
f'{__name__}.Typos', autospect=True, set_spec=True, auto_spec=True):
pass
def test_property_not_called_with_spec_mock(self):
obj = SomethingElse()
self.assertIsNone(obj._instance, msg='before mock')
mock = Mock(spec=obj)
self.assertIsNone(obj._instance, msg='after mock')
self.assertEqual('object', obj.instance)
def test_decorated_async_methods_with_spec_mock(self):
class Foo():
@classmethod
async def class_method(cls):
pass
@staticmethod
async def static_method():
pass
async def method(self):
pass
mock = Mock(spec=Foo)
for m in (mock.method, mock.class_method, mock.static_method):
self.assertIsInstance(m, AsyncMock)
if __name__ == '__main__':
unittest.main()

View File

@ -526,7 +526,13 @@ class NonCallableMock(Base):
spec_list = dir(spec)
for attr in spec_list:
if iscoroutinefunction(getattr(spec, attr, None)):
static_attr = inspect.getattr_static(spec, attr, None)
unwrapped_attr = static_attr
try:
unwrapped_attr = inspect.unwrap(unwrapped_attr)
except ValueError:
pass
if iscoroutinefunction(unwrapped_attr):
_spec_asyncs.append(attr)
spec = spec_list

View File

@ -0,0 +1,2 @@
:mod:`unittest.mock` speccing no longer calls class properties.
Patch by Melanie Witt.