mirror of
https://github.com/python/cpython.git
synced 2025-09-26 18:29:57 +00:00
bpo-23078: Add support for {class,static}method to mock.create_autospec() (GH-11613)
Co-authored-by: Felipe <felipe.nospam.ochoa@gmail.com>
This commit is contained in:
parent
9541bd321a
commit
9b21856b0f
5 changed files with 81 additions and 2 deletions
|
@ -29,7 +29,7 @@ import inspect
|
||||||
import pprint
|
import pprint
|
||||||
import sys
|
import sys
|
||||||
import builtins
|
import builtins
|
||||||
from types import ModuleType
|
from types import ModuleType, MethodType
|
||||||
from unittest.util import safe_repr
|
from unittest.util import safe_repr
|
||||||
from functools import wraps, partial
|
from functools import wraps, partial
|
||||||
|
|
||||||
|
@ -122,6 +122,8 @@ def _copy_func_details(func, funcopy):
|
||||||
def _callable(obj):
|
def _callable(obj):
|
||||||
if isinstance(obj, type):
|
if isinstance(obj, type):
|
||||||
return True
|
return True
|
||||||
|
if isinstance(obj, (staticmethod, classmethod, MethodType)):
|
||||||
|
return _callable(obj.__func__)
|
||||||
if getattr(obj, '__call__', None) is not None:
|
if getattr(obj, '__call__', None) is not None:
|
||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
|
|
|
@ -5,7 +5,7 @@ import unittest
|
||||||
|
|
||||||
from unittest.mock import (
|
from unittest.mock import (
|
||||||
call, _Call, create_autospec, MagicMock,
|
call, _Call, create_autospec, MagicMock,
|
||||||
Mock, ANY, _CallList, patch, PropertyMock
|
Mock, ANY, _CallList, patch, PropertyMock, _callable
|
||||||
)
|
)
|
||||||
|
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
|
@ -1011,5 +1011,43 @@ class TestCallList(unittest.TestCase):
|
||||||
self.assertNotIsInstance(returned, PropertyMock)
|
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__':
|
if __name__ == '__main__':
|
||||||
unittest.main()
|
unittest.main()
|
||||||
|
|
|
@ -1419,6 +1419,23 @@ class MockTest(unittest.TestCase):
|
||||||
m = mock.create_autospec(object(), name='sweet_func')
|
m = mock.create_autospec(object(), name='sweet_func')
|
||||||
self.assertIn('sweet_func', repr(m))
|
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
|
#Issue21238
|
||||||
def test_mock_unsafe(self):
|
def test_mock_unsafe(self):
|
||||||
m = Mock()
|
m = Mock()
|
||||||
|
|
|
@ -51,6 +51,14 @@ class Foo(object):
|
||||||
pass
|
pass
|
||||||
foo = 'bar'
|
foo = 'bar'
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def static_method():
|
||||||
|
return 24
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def class_method(cls):
|
||||||
|
return 42
|
||||||
|
|
||||||
class Bar(object):
|
class Bar(object):
|
||||||
def a(self):
|
def a(self):
|
||||||
pass
|
pass
|
||||||
|
@ -1023,6 +1031,18 @@ class PatchTest(unittest.TestCase):
|
||||||
self.assertEqual(result, 3)
|
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):
|
def test_autospec_with_new(self):
|
||||||
patcher = patch('%s.function' % __name__, new=3, autospec=True)
|
patcher = patch('%s.function' % __name__, new=3, autospec=True)
|
||||||
self.assertRaises(TypeError, patcher.start)
|
self.assertRaises(TypeError, patcher.start)
|
||||||
|
|
|
@ -0,0 +1,2 @@
|
||||||
|
Add support for :func:`classmethod` and :func:`staticmethod` to
|
||||||
|
:func:`unittest.mock.create_autospec`. Initial patch by Felipe Ochoa.
|
Loading…
Add table
Add a link
Reference in a new issue