diff -r c2c4400bb12c Lib/unittest/mock.py --- a/Lib/unittest/mock.py Mon Sep 14 01:03:04 2015 -0400 +++ b/Lib/unittest/mock.py Mon Sep 14 19:42:13 2015 -0400 @@ -28,7 +28,7 @@ import pprint import sys import builtins -from types import ModuleType +from types import ModuleType, MethodType from functools import wraps, partial @@ -139,6 +139,8 @@ 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 -r c2c4400bb12c Lib/unittest/test/testmock/testhelpers.py --- a/Lib/unittest/test/testmock/testhelpers.py Mon Sep 14 01:03:04 2015 -0400 +++ b/Lib/unittest/test/testmock/testhelpers.py Mon Sep 14 19:42:13 2015 -0400 @@ -2,7 +2,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 @@ -904,5 +904,43 @@ 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(object): + def __call__(self): + pass + instance = Callable() + self.assertTrue(_callable(instance)) + + def test_staticmethod(self): + class WithStaticMethod(object): + @staticmethod + def staticfunc(): + pass + self.assertTrue(_callable(WithStaticMethod.staticfunc)) + + def test_non_callable_staticmethod(self): + class BadStaticMethod(object): + not_callable = staticmethod(None) + self.assertFalse(_callable(BadStaticMethod.not_callable)) + + def test_classmethod(self): + class WithClassMethod(object): + @classmethod + def classfunc(cls): + pass + self.assertTrue(_callable(WithClassMethod.classfunc)) + + def test_non_callable_classmethod(self): + class BadClassMethod(object): + not_callable = classmethod(None) + self.assertFalse(_callable(BadClassMethod.not_callable)) + + if __name__ == '__main__': unittest.main() diff -r c2c4400bb12c Lib/unittest/test/testmock/testmock.py --- a/Lib/unittest/test/testmock/testmock.py Mon Sep 14 01:03:04 2015 -0400 +++ b/Lib/unittest/test/testmock/testmock.py Mon Sep 14 19:42:13 2015 -0400 @@ -1203,6 +1203,24 @@ m = mock.create_autospec(object(), name='sweet_func') self.assertIn('sweet_func', repr(m)) + #Issue23078 + def test_create_autospec_classmethod(self): + class TestClass: + method = classmethod(lambda cls: None) + mock_bound_meth = mock.create_autospec(TestClass.method) + mock_bound_meth() + mock_bound_meth.assert_called_once_with() + self.assertRaises(TypeError, mock_bound_meth, 'extra_arg') + + #Issue23078 + def test_create_autospec_staticmethod(self): + class TestClass: + method = staticmethod(lambda: None) + mock_meth = mock.create_autospec(TestClass.method) + mock_meth() + mock_meth.assert_called_once_with() + self.assertRaises(TypeError, mock_meth, 'extra_arg') + #Issue21238 def test_mock_unsafe(self): m = Mock() diff -r c2c4400bb12c Lib/unittest/test/testmock/testpatch.py --- a/Lib/unittest/test/testmock/testpatch.py Mon Sep 14 01:03:04 2015 -0400 +++ b/Lib/unittest/test/testmock/testpatch.py Mon Sep 14 19:42:13 2015 -0400 @@ -50,6 +50,14 @@ pass foo = 'bar' + @staticmethod + def a_static(): + return 24 + + @classmethod + def a_class(cls): + return 42 + class Bar(object): def a(self): pass @@ -991,6 +999,18 @@ self.assertEqual(result, 3) + def test_autospec_staticmethod(self): + with patch('%s.Foo.a_static' % __name__, autospec=True) as method: + Foo.a_static() + method.assert_called_once_with() + + + def test_autospec_classmethod(self): + with patch('%s.Foo.a_class' % __name__, autospec=True) as method: + Foo.a_class() + 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)