Skip to content

Commit

Permalink
pythongh-85934: Use getattr_static when adding mock spec (python#22209)
Browse files Browse the repository at this point in the history
Co-authored-by: Terry Jan Reedy <tjreedy@udel.edu>
Co-authored-by: Oleg Iarygin <oleg@arhadthedev.net>
  • Loading branch information
3 people authored May 23, 2023
1 parent 6b1510c commit 2e09310
Show file tree
Hide file tree
Showing 3 changed files with 40 additions and 1 deletion.
31 changes: 31 additions & 0 deletions Lib/test/test_unittest/testmock/testmock.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,17 @@ def cmeth(cls, a, b, c, d=None): pass
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
Expand Down Expand Up @@ -2293,6 +2304,26 @@ class Foo():
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()
8 changes: 7 additions & 1 deletion Lib/unittest/mock.py
Original file line number Diff line number Diff line change
Expand Up @@ -526,7 +526,13 @@ def _mock_add_spec(self, spec, spec_set, _spec_as_instance=False,
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
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
:mod:`unittest.mock` speccing no longer calls class properties.
Patch by Melanie Witt.

0 comments on commit 2e09310

Please sign in to comment.