[Python-checkins] bpo-23078: Add support for {class, static}method to mock.create_autospec() (GH-11613)
Berker Peksag
webhook-mailer at python.org
Sun Apr 21 22:30:26 EDT 2019
https://github.com/python/cpython/commit/9b21856b0fcda949de239edc7aa6cf3f2f4f77a3
commit: 9b21856b0fcda949de239edc7aa6cf3f2f4f77a3
branch: master
author: Xtreak <tir.karthi at gmail.com>
committer: Berker Peksag <berker.peksag at gmail.com>
date: 2019-04-22T05:30:23+03:00
summary:
bpo-23078: Add support for {class,static}method to mock.create_autospec() (GH-11613)
Co-authored-by: Felipe <felipe.nospam.ochoa at gmail.com>
files:
A Misc/NEWS.d/next/Library/2019-01-18-23-10-10.bpo-23078.l4dFoj.rst
M Lib/unittest/mock.py
M Lib/unittest/test/testmock/testhelpers.py
M Lib/unittest/test/testmock/testmock.py
M Lib/unittest/test/testmock/testpatch.py
diff --git a/Lib/unittest/mock.py b/Lib/unittest/mock.py
index 0e77f0e48943..1636073ff009 100644
--- a/Lib/unittest/mock.py
+++ b/Lib/unittest/mock.py
@@ -29,7 +29,7 @@
import pprint
import sys
import builtins
-from types import ModuleType
+from types import ModuleType, MethodType
from unittest.util import safe_repr
from functools import wraps, partial
@@ -122,6 +122,8 @@ def _copy_func_details(func, funcopy):
def _callable(obj):
if isinstance(obj, type):
return True
+ if isinstance(obj, (staticmethod, classmethod, MethodType)):
+ return _callable(obj.__func__)
if getattr(obj, '__call__', None) is not None:
return True
return False
diff --git a/Lib/unittest/test/testmock/testhelpers.py b/Lib/unittest/test/testmock/testhelpers.py
index 9f1bf2676bf5..0d03108aca55 100644
--- a/Lib/unittest/test/testmock/testhelpers.py
+++ b/Lib/unittest/test/testmock/testhelpers.py
@@ -5,7 +5,7 @@
from unittest.mock import (
call, _Call, create_autospec, MagicMock,
- Mock, ANY, _CallList, patch, PropertyMock
+ Mock, ANY, _CallList, patch, PropertyMock, _callable
)
from datetime import datetime
@@ -1011,5 +1011,43 @@ def test_propertymock_returnvalue(self):
self.assertNotIsInstance(returned, PropertyMock)
+class TestCallablePredicate(unittest.TestCase):
+
+ def test_type(self):
+ for obj in [str, bytes, int, list, tuple, SomeClass]:
+ self.assertTrue(_callable(obj))
+
+ def test_call_magic_method(self):
+ class Callable:
+ def __call__(self):
+ pass
+ instance = Callable()
+ self.assertTrue(_callable(instance))
+
+ def test_staticmethod(self):
+ class WithStaticMethod:
+ @staticmethod
+ def staticfunc():
+ pass
+ self.assertTrue(_callable(WithStaticMethod.staticfunc))
+
+ def test_non_callable_staticmethod(self):
+ class BadStaticMethod:
+ not_callable = staticmethod(None)
+ self.assertFalse(_callable(BadStaticMethod.not_callable))
+
+ def test_classmethod(self):
+ class WithClassMethod:
+ @classmethod
+ def classfunc(cls):
+ pass
+ self.assertTrue(_callable(WithClassMethod.classfunc))
+
+ def test_non_callable_classmethod(self):
+ class BadClassMethod:
+ not_callable = classmethod(None)
+ self.assertFalse(_callable(BadClassMethod.not_callable))
+
+
if __name__ == '__main__':
unittest.main()
diff --git a/Lib/unittest/test/testmock/testmock.py b/Lib/unittest/test/testmock/testmock.py
index 37f14c37f47d..bdaebbe66b74 100644
--- a/Lib/unittest/test/testmock/testmock.py
+++ b/Lib/unittest/test/testmock/testmock.py
@@ -1419,6 +1419,23 @@ def test_create_autospec_with_name(self):
m = mock.create_autospec(object(), name='sweet_func')
self.assertIn('sweet_func', repr(m))
+ #Issue23078
+ def test_create_autospec_classmethod_and_staticmethod(self):
+ class TestClass:
+ @classmethod
+ def class_method(cls):
+ pass
+
+ @staticmethod
+ def static_method():
+ pass
+ for method in ('class_method', 'static_method'):
+ with self.subTest(method=method):
+ mock_method = mock.create_autospec(getattr(TestClass, method))
+ mock_method()
+ mock_method.assert_called_once_with()
+ self.assertRaises(TypeError, mock_method, 'extra_arg')
+
#Issue21238
def test_mock_unsafe(self):
m = Mock()
diff --git a/Lib/unittest/test/testmock/testpatch.py b/Lib/unittest/test/testmock/testpatch.py
index 2c14360b2df5..51c66fec67fc 100644
--- a/Lib/unittest/test/testmock/testpatch.py
+++ b/Lib/unittest/test/testmock/testpatch.py
@@ -51,6 +51,14 @@ def g(self):
pass
foo = 'bar'
+ @staticmethod
+ def static_method():
+ return 24
+
+ @classmethod
+ def class_method(cls):
+ return 42
+
class Bar(object):
def a(self):
pass
@@ -1023,6 +1031,18 @@ def test(mock_function):
self.assertEqual(result, 3)
+ def test_autospec_staticmethod(self):
+ with patch('%s.Foo.static_method' % __name__, autospec=True) as method:
+ Foo.static_method()
+ method.assert_called_once_with()
+
+
+ def test_autospec_classmethod(self):
+ with patch('%s.Foo.class_method' % __name__, autospec=True) as method:
+ Foo.class_method()
+ method.assert_called_once_with()
+
+
def test_autospec_with_new(self):
patcher = patch('%s.function' % __name__, new=3, autospec=True)
self.assertRaises(TypeError, patcher.start)
diff --git a/Misc/NEWS.d/next/Library/2019-01-18-23-10-10.bpo-23078.l4dFoj.rst b/Misc/NEWS.d/next/Library/2019-01-18-23-10-10.bpo-23078.l4dFoj.rst
new file mode 100644
index 000000000000..975cc9c0454c
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2019-01-18-23-10-10.bpo-23078.l4dFoj.rst
@@ -0,0 +1,2 @@
+Add support for :func:`classmethod` and :func:`staticmethod` to
+:func:`unittest.mock.create_autospec`. Initial patch by Felipe Ochoa.
More information about the Python-checkins
mailing list