Skip to content

Commit 2e09310

Browse files
melwittterryjreedyarhadthedev
authored
gh-85934: Use getattr_static when adding mock spec (#22209)
Co-authored-by: Terry Jan Reedy <[email protected]> Co-authored-by: Oleg Iarygin <[email protected]>
1 parent 6b1510c commit 2e09310

File tree

3 files changed

+40
-1
lines changed

3 files changed

+40
-1
lines changed

Lib/test/test_unittest/testmock/testmock.py

+31
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,17 @@ def cmeth(cls, a, b, c, d=None): pass
3838
def smeth(a, b, c, d=None): pass
3939

4040

41+
class SomethingElse(object):
42+
def __init__(self):
43+
self._instance = None
44+
45+
@property
46+
def instance(self):
47+
if not self._instance:
48+
self._instance = 'object'
49+
return self._instance
50+
51+
4152
class Typos():
4253
autospect = None
4354
auto_spec = None
@@ -2293,6 +2304,26 @@ class Foo():
22932304
f'{__name__}.Typos', autospect=True, set_spec=True, auto_spec=True):
22942305
pass
22952306

2307+
def test_property_not_called_with_spec_mock(self):
2308+
obj = SomethingElse()
2309+
self.assertIsNone(obj._instance, msg='before mock')
2310+
mock = Mock(spec=obj)
2311+
self.assertIsNone(obj._instance, msg='after mock')
2312+
self.assertEqual('object', obj.instance)
2313+
2314+
def test_decorated_async_methods_with_spec_mock(self):
2315+
class Foo():
2316+
@classmethod
2317+
async def class_method(cls):
2318+
pass
2319+
@staticmethod
2320+
async def static_method():
2321+
pass
2322+
async def method(self):
2323+
pass
2324+
mock = Mock(spec=Foo)
2325+
for m in (mock.method, mock.class_method, mock.static_method):
2326+
self.assertIsInstance(m, AsyncMock)
22962327

22972328
if __name__ == '__main__':
22982329
unittest.main()

Lib/unittest/mock.py

+7-1
Original file line numberDiff line numberDiff line change
@@ -526,7 +526,13 @@ def _mock_add_spec(self, spec, spec_set, _spec_as_instance=False,
526526
spec_list = dir(spec)
527527

528528
for attr in spec_list:
529-
if iscoroutinefunction(getattr(spec, attr, None)):
529+
static_attr = inspect.getattr_static(spec, attr, None)
530+
unwrapped_attr = static_attr
531+
try:
532+
unwrapped_attr = inspect.unwrap(unwrapped_attr)
533+
except ValueError:
534+
pass
535+
if iscoroutinefunction(unwrapped_attr):
530536
_spec_asyncs.append(attr)
531537

532538
spec = spec_list
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
:mod:`unittest.mock` speccing no longer calls class properties.
2+
Patch by Melanie Witt.

0 commit comments

Comments
 (0)