aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
authormelanie witt <melwittt@gmail.com>2023-05-23 16:10:34 -0700
committerGitHub <noreply@github.com>2023-05-23 17:10:34 -0600
commit2e0931046dcc200fd6abb2cdfaf57d8b99117c57 (patch)
treeebb46d171eacd829f6ec537077a812676393d4ca
parent6b1510cf11c16c8e4381810c15ceeda6f89e79f4 (diff)
downloadcpython-2e0931046dcc200fd6abb2cdfaf57d8b99117c57.tar.gz
cpython-2e0931046dcc200fd6abb2cdfaf57d8b99117c57.zip
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>
-rw-r--r--Lib/test/test_unittest/testmock/testmock.py31
-rw-r--r--Lib/unittest/mock.py8
-rw-r--r--Misc/NEWS.d/next/Library/2020-09-16-16-53-06.bpo-41768.8_fWkC.rst2
3 files changed, 40 insertions, 1 deletions
diff --git a/Lib/test/test_unittest/testmock/testmock.py b/Lib/test/test_unittest/testmock/testmock.py
index d1cae47a40e..c7895e73ad9 100644
--- a/Lib/test/test_unittest/testmock/testmock.py
+++ b/Lib/test/test_unittest/testmock/testmock.py
@@ -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()
diff --git a/Lib/unittest/mock.py b/Lib/unittest/mock.py
index 7ca08576065..22f81e55b56 100644
--- a/Lib/unittest/mock.py
+++ b/Lib/unittest/mock.py
@@ -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
diff --git a/Misc/NEWS.d/next/Library/2020-09-16-16-53-06.bpo-41768.8_fWkC.rst b/Misc/NEWS.d/next/Library/2020-09-16-16-53-06.bpo-41768.8_fWkC.rst
new file mode 100644
index 00000000000..bfd3a294d44
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2020-09-16-16-53-06.bpo-41768.8_fWkC.rst
@@ -0,0 +1,2 @@
+:mod:`unittest.mock` speccing no longer calls class properties.
+Patch by Melanie Witt.