mirror of
https://github.com/python/cpython.git
synced 2025-07-24 03:35:53 +00:00
Mock 100% coverage (GH-13045)
This was achieved by: * moving many pass statements in tests onto their own lines, so they pass line coverage and can match an easy ignore pattern if branch coverage is added later. * removing code that cannot be reached. * removing long-disabled tests. * removing unused code. * adding tests for uncovered code It turned out that removing `if __name__ == '__main__'` blocks that run unittest.main() at the bottom of test files was surprisingly contentious, so they remain and can be filtered out with an appropriate .coveragerc.
This commit is contained in:
parent
b7378d7728
commit
adbf178e49
9 changed files with 263 additions and 317 deletions
|
@ -63,10 +63,7 @@ def _get_signature_object(func, as_instance, eat_self):
|
|||
"""
|
||||
if isinstance(func, type) and not as_instance:
|
||||
# If it's a type and should be modelled as a type, use __init__.
|
||||
try:
|
||||
func = func.__init__
|
||||
except AttributeError:
|
||||
return None
|
||||
func = func.__init__
|
||||
# Skip the `self` argument in __init__
|
||||
eat_self = True
|
||||
elif not isinstance(func, FunctionTypes):
|
||||
|
@ -147,8 +144,6 @@ def _set_signature(mock, original, instance=False):
|
|||
# creates a function with signature (*args, **kwargs) that delegates to a
|
||||
# mock. It still does signature checking by calling a lambda with the same
|
||||
# signature as the original.
|
||||
if not _callable(original):
|
||||
return
|
||||
|
||||
skipfirst = isinstance(original, type)
|
||||
result = _get_signature_object(original, instance, skipfirst)
|
||||
|
@ -175,10 +170,6 @@ def _set_signature(mock, original, instance=False):
|
|||
def _setup_func(funcopy, mock, sig):
|
||||
funcopy.mock = mock
|
||||
|
||||
# can't use isinstance with mocks
|
||||
if not _is_instance_mock(mock):
|
||||
return
|
||||
|
||||
def assert_called_with(*args, **kwargs):
|
||||
return mock.assert_called_with(*args, **kwargs)
|
||||
def assert_called(*args, **kwargs):
|
||||
|
@ -263,12 +254,6 @@ _missing = sentinel.MISSING
|
|||
_deleted = sentinel.DELETED
|
||||
|
||||
|
||||
def _copy(value):
|
||||
if type(value) in (dict, list, tuple, set):
|
||||
return type(value)(value)
|
||||
return value
|
||||
|
||||
|
||||
_allowed_names = {
|
||||
'return_value', '_mock_return_value', 'side_effect',
|
||||
'_mock_side_effect', '_mock_parent', '_mock_new_parent',
|
||||
|
@ -351,8 +336,6 @@ def _check_and_set_parent(parent, value, name, new_name):
|
|||
class _MockIter(object):
|
||||
def __init__(self, obj):
|
||||
self.obj = iter(obj)
|
||||
def __iter__(self):
|
||||
return self
|
||||
def __next__(self):
|
||||
return next(self.obj)
|
||||
|
||||
|
@ -452,7 +435,7 @@ class NonCallableMock(Base):
|
|||
if isinstance(spec, type):
|
||||
_spec_class = spec
|
||||
else:
|
||||
_spec_class = _get_class(spec)
|
||||
_spec_class = type(spec)
|
||||
res = _get_signature_object(spec,
|
||||
_spec_as_instance, _eat_self)
|
||||
_spec_signature = res and res[1]
|
||||
|
@ -624,7 +607,7 @@ class NonCallableMock(Base):
|
|||
dot = '.'
|
||||
if _name_list == ['()']:
|
||||
dot = ''
|
||||
seen = set()
|
||||
|
||||
while _parent is not None:
|
||||
last = _parent
|
||||
|
||||
|
@ -635,11 +618,6 @@ class NonCallableMock(Base):
|
|||
|
||||
_parent = _parent._mock_new_parent
|
||||
|
||||
# use ids here so as not to call __hash__ on the mocks
|
||||
if id(_parent) in seen:
|
||||
break
|
||||
seen.add(id(_parent))
|
||||
|
||||
_name_list = list(reversed(_name_list))
|
||||
_first = last._mock_name or 'mock'
|
||||
if len(_name_list) > 1:
|
||||
|
@ -753,8 +731,6 @@ class NonCallableMock(Base):
|
|||
message = 'expected call not found.\nExpected: %s\nActual: %s'
|
||||
expected_string = self._format_mock_call_signature(args, kwargs)
|
||||
call_args = self.call_args
|
||||
if len(call_args) == 3:
|
||||
call_args = call_args[1:]
|
||||
actual_string = self._format_mock_call_signature(*call_args)
|
||||
return message % (expected_string, actual_string)
|
||||
|
||||
|
@ -992,8 +968,6 @@ class CallableMixin(Base):
|
|||
self.call_args = _call
|
||||
self.call_args_list.append(_call)
|
||||
|
||||
seen = set()
|
||||
|
||||
# initial stuff for method_calls:
|
||||
do_method_calls = self._mock_parent is not None
|
||||
method_call_name = self._mock_name
|
||||
|
@ -1029,13 +1003,6 @@ class CallableMixin(Base):
|
|||
# follow the parental chain:
|
||||
_new_parent = _new_parent._mock_new_parent
|
||||
|
||||
# check we're not in an infinite loop:
|
||||
# ( use ids here so as not to call __hash__ on the mocks)
|
||||
_new_parent_id = id(_new_parent)
|
||||
if _new_parent_id in seen:
|
||||
break
|
||||
seen.add(_new_parent_id)
|
||||
|
||||
effect = self.side_effect
|
||||
if effect is not None:
|
||||
if _is_exception(effect):
|
||||
|
@ -1858,12 +1825,7 @@ def _set_return_value(mock, method, name):
|
|||
|
||||
return_calulator = _calculate_return_value.get(name)
|
||||
if return_calulator is not None:
|
||||
try:
|
||||
return_value = return_calulator(mock)
|
||||
except AttributeError:
|
||||
# XXXX why do we return AttributeError here?
|
||||
# set it as a side_effect instead?
|
||||
return_value = AttributeError(name)
|
||||
return_value = return_calulator(mock)
|
||||
method.return_value = return_value
|
||||
return
|
||||
|
||||
|
@ -1943,10 +1905,6 @@ class MagicProxy(object):
|
|||
self.name = name
|
||||
self.parent = parent
|
||||
|
||||
def __call__(self, *args, **kwargs):
|
||||
m = self.create_mock()
|
||||
return m(*args, **kwargs)
|
||||
|
||||
def create_mock(self):
|
||||
entry = self.name
|
||||
parent = self.parent
|
||||
|
@ -2330,19 +2288,10 @@ def _must_skip(spec, entry, is_type):
|
|||
else:
|
||||
return False
|
||||
|
||||
# shouldn't get here unless function is a dynamically provided attribute
|
||||
# XXXX untested behaviour
|
||||
# function is a dynamically provided attribute
|
||||
return is_type
|
||||
|
||||
|
||||
def _get_class(obj):
|
||||
try:
|
||||
return obj.__class__
|
||||
except AttributeError:
|
||||
# it is possible for objects to have no __class__
|
||||
return type(obj)
|
||||
|
||||
|
||||
class _SpecState(object):
|
||||
|
||||
def __init__(self, spec, spec_set=False, parent=None,
|
||||
|
|
|
@ -9,8 +9,7 @@ def is_instance(obj, klass):
|
|||
class SomeClass(object):
|
||||
class_attribute = None
|
||||
|
||||
def wibble(self):
|
||||
pass
|
||||
def wibble(self): pass
|
||||
|
||||
|
||||
class X(object):
|
||||
|
|
|
@ -98,8 +98,7 @@ class TestCallable(unittest.TestCase):
|
|||
|
||||
def test_patch_spec_callable_class(self):
|
||||
class CallableX(X):
|
||||
def __call__(self):
|
||||
pass
|
||||
def __call__(self): pass
|
||||
|
||||
class Sub(CallableX):
|
||||
pass
|
||||
|
|
|
@ -12,12 +12,9 @@ from datetime import datetime
|
|||
from functools import partial
|
||||
|
||||
class SomeClass(object):
|
||||
def one(self, a, b):
|
||||
pass
|
||||
def two(self):
|
||||
pass
|
||||
def three(self, a=None):
|
||||
pass
|
||||
def one(self, a, b): pass
|
||||
def two(self): pass
|
||||
def three(self, a=None): pass
|
||||
|
||||
|
||||
|
||||
|
@ -48,12 +45,9 @@ class AnyTest(unittest.TestCase):
|
|||
|
||||
def test_any_mock_calls_comparison_order(self):
|
||||
mock = Mock()
|
||||
d = datetime.now()
|
||||
class Foo(object):
|
||||
def __eq__(self, other):
|
||||
return False
|
||||
def __ne__(self, other):
|
||||
return True
|
||||
def __eq__(self, other): pass
|
||||
def __ne__(self, other): pass
|
||||
|
||||
for d in datetime.now(), Foo():
|
||||
mock.reset_mock()
|
||||
|
@ -378,8 +372,7 @@ class SpecSignatureTest(unittest.TestCase):
|
|||
|
||||
|
||||
def test_create_autospec_return_value(self):
|
||||
def f():
|
||||
pass
|
||||
def f(): pass
|
||||
mock = create_autospec(f, return_value='foo')
|
||||
self.assertEqual(mock(), 'foo')
|
||||
|
||||
|
@ -399,8 +392,7 @@ class SpecSignatureTest(unittest.TestCase):
|
|||
|
||||
def test_mocking_unbound_methods(self):
|
||||
class Foo(object):
|
||||
def foo(self, foo):
|
||||
pass
|
||||
def foo(self, foo): pass
|
||||
p = patch.object(Foo, 'foo')
|
||||
mock_foo = p.start()
|
||||
Foo().foo(1)
|
||||
|
@ -408,24 +400,6 @@ class SpecSignatureTest(unittest.TestCase):
|
|||
mock_foo.assert_called_with(1)
|
||||
|
||||
|
||||
def test_create_autospec_unbound_methods(self):
|
||||
# see mock issue 128
|
||||
# this is expected to fail until the issue is fixed
|
||||
return
|
||||
class Foo(object):
|
||||
def foo(self):
|
||||
pass
|
||||
|
||||
klass = create_autospec(Foo)
|
||||
instance = klass()
|
||||
self.assertRaises(TypeError, instance.foo, 1)
|
||||
|
||||
# Note: no type checking on the "self" parameter
|
||||
klass.foo(1)
|
||||
klass.foo.assert_called_with(1)
|
||||
self.assertRaises(TypeError, klass.foo)
|
||||
|
||||
|
||||
def test_create_autospec_keyword_arguments(self):
|
||||
class Foo(object):
|
||||
a = 3
|
||||
|
@ -434,8 +408,7 @@ class SpecSignatureTest(unittest.TestCase):
|
|||
|
||||
|
||||
def test_create_autospec_keyword_only_arguments(self):
|
||||
def foo(a, *, b=None):
|
||||
pass
|
||||
def foo(a, *, b=None): pass
|
||||
|
||||
m = create_autospec(foo)
|
||||
m(1)
|
||||
|
@ -448,8 +421,7 @@ class SpecSignatureTest(unittest.TestCase):
|
|||
|
||||
def test_function_as_instance_attribute(self):
|
||||
obj = SomeClass()
|
||||
def f(a):
|
||||
pass
|
||||
def f(a): pass
|
||||
obj.f = f
|
||||
|
||||
mock = create_autospec(obj)
|
||||
|
@ -485,13 +457,57 @@ class SpecSignatureTest(unittest.TestCase):
|
|||
self._check_someclass_mock(mock)
|
||||
|
||||
|
||||
def test_spec_has_descriptor_returning_function(self):
|
||||
|
||||
class CrazyDescriptor(object):
|
||||
|
||||
def __get__(self, obj, type_):
|
||||
if obj is None:
|
||||
return lambda x: None
|
||||
|
||||
class MyClass(object):
|
||||
|
||||
some_attr = CrazyDescriptor()
|
||||
|
||||
mock = create_autospec(MyClass)
|
||||
mock.some_attr(1)
|
||||
with self.assertRaises(TypeError):
|
||||
mock.some_attr()
|
||||
with self.assertRaises(TypeError):
|
||||
mock.some_attr(1, 2)
|
||||
|
||||
|
||||
def test_spec_has_function_not_in_bases(self):
|
||||
|
||||
class CrazyClass(object):
|
||||
|
||||
def __dir__(self):
|
||||
return super(CrazyClass, self).__dir__()+['crazy']
|
||||
|
||||
def __getattr__(self, item):
|
||||
if item == 'crazy':
|
||||
return lambda x: x
|
||||
raise AttributeError(item)
|
||||
|
||||
inst = CrazyClass()
|
||||
with self.assertRaises(AttributeError):
|
||||
inst.other
|
||||
self.assertEqual(inst.crazy(42), 42)
|
||||
|
||||
mock = create_autospec(inst)
|
||||
mock.crazy(42)
|
||||
with self.assertRaises(TypeError):
|
||||
mock.crazy()
|
||||
with self.assertRaises(TypeError):
|
||||
mock.crazy(1, 2)
|
||||
|
||||
|
||||
def test_builtin_functions_types(self):
|
||||
# we could replace builtin functions / methods with a function
|
||||
# with *args / **kwargs signature. Using the builtin method type
|
||||
# as a spec seems to work fairly well though.
|
||||
class BuiltinSubclass(list):
|
||||
def bar(self, arg):
|
||||
pass
|
||||
def bar(self, arg): pass
|
||||
sorted = sorted
|
||||
attr = {}
|
||||
|
||||
|
@ -565,17 +581,13 @@ class SpecSignatureTest(unittest.TestCase):
|
|||
def test_descriptors(self):
|
||||
class Foo(object):
|
||||
@classmethod
|
||||
def f(cls, a, b):
|
||||
pass
|
||||
def f(cls, a, b): pass
|
||||
@staticmethod
|
||||
def g(a, b):
|
||||
pass
|
||||
def g(a, b): pass
|
||||
|
||||
class Bar(Foo):
|
||||
pass
|
||||
class Bar(Foo): pass
|
||||
|
||||
class Baz(SomeClass, Bar):
|
||||
pass
|
||||
class Baz(SomeClass, Bar): pass
|
||||
|
||||
for spec in (Foo, Foo(), Bar, Bar(), Baz, Baz()):
|
||||
mock = create_autospec(spec)
|
||||
|
@ -588,8 +600,7 @@ class SpecSignatureTest(unittest.TestCase):
|
|||
|
||||
def test_recursive(self):
|
||||
class A(object):
|
||||
def a(self):
|
||||
pass
|
||||
def a(self): pass
|
||||
foo = 'foo bar baz'
|
||||
bar = foo
|
||||
|
||||
|
@ -611,11 +622,9 @@ class SpecSignatureTest(unittest.TestCase):
|
|||
|
||||
def test_spec_inheritance_for_classes(self):
|
||||
class Foo(object):
|
||||
def a(self, x):
|
||||
pass
|
||||
def a(self, x): pass
|
||||
class Bar(object):
|
||||
def f(self, y):
|
||||
pass
|
||||
def f(self, y): pass
|
||||
|
||||
class_mock = create_autospec(Foo)
|
||||
|
||||
|
@ -695,8 +704,7 @@ class SpecSignatureTest(unittest.TestCase):
|
|||
|
||||
|
||||
def test_function(self):
|
||||
def f(a, b):
|
||||
pass
|
||||
def f(a, b): pass
|
||||
|
||||
mock = create_autospec(f)
|
||||
self.assertRaises(TypeError, mock)
|
||||
|
@ -726,9 +734,10 @@ class SpecSignatureTest(unittest.TestCase):
|
|||
def existing(a, b):
|
||||
return a + b
|
||||
|
||||
self.assertEqual(RaiserClass.existing(1, 2), 3)
|
||||
s = create_autospec(RaiserClass)
|
||||
self.assertRaises(TypeError, lambda x: s.existing(1, 2, 3))
|
||||
s.existing(1, 2)
|
||||
self.assertEqual(s.existing(1, 2), s.existing.return_value)
|
||||
self.assertRaises(AttributeError, lambda: s.nonexisting)
|
||||
|
||||
# check we can fetch the raiser attribute and it has no spec
|
||||
|
@ -738,8 +747,7 @@ class SpecSignatureTest(unittest.TestCase):
|
|||
|
||||
def test_signature_class(self):
|
||||
class Foo(object):
|
||||
def __init__(self, a, b=3):
|
||||
pass
|
||||
def __init__(self, a, b=3): pass
|
||||
|
||||
mock = create_autospec(Foo)
|
||||
|
||||
|
@ -765,10 +773,8 @@ class SpecSignatureTest(unittest.TestCase):
|
|||
|
||||
def test_signature_callable(self):
|
||||
class Callable(object):
|
||||
def __init__(self, x, y):
|
||||
pass
|
||||
def __call__(self, a):
|
||||
pass
|
||||
def __init__(self, x, y): pass
|
||||
def __call__(self, a): pass
|
||||
|
||||
mock = create_autospec(Callable)
|
||||
mock(1, 2)
|
||||
|
@ -824,8 +830,7 @@ class SpecSignatureTest(unittest.TestCase):
|
|||
|
||||
def test_autospec_functions_with_self_in_odd_place(self):
|
||||
class Foo(object):
|
||||
def f(a, self):
|
||||
pass
|
||||
def f(a, self): pass
|
||||
|
||||
a = create_autospec(Foo)
|
||||
a.f(10)
|
||||
|
@ -842,12 +847,9 @@ class SpecSignatureTest(unittest.TestCase):
|
|||
self.value = value
|
||||
|
||||
def __get__(self, obj, cls=None):
|
||||
if obj is None:
|
||||
return self
|
||||
return self.value
|
||||
return self
|
||||
|
||||
def __set__(self, obj, value):
|
||||
pass
|
||||
def __set__(self, obj, value): pass
|
||||
|
||||
class MyProperty(property):
|
||||
pass
|
||||
|
@ -856,12 +858,10 @@ class SpecSignatureTest(unittest.TestCase):
|
|||
__slots__ = ['slot']
|
||||
|
||||
@property
|
||||
def prop(self):
|
||||
return 3
|
||||
def prop(self): pass
|
||||
|
||||
@MyProperty
|
||||
def subprop(self):
|
||||
return 4
|
||||
def subprop(self): pass
|
||||
|
||||
desc = Descriptor(42)
|
||||
|
||||
|
@ -913,8 +913,7 @@ class SpecSignatureTest(unittest.TestCase):
|
|||
|
||||
def test_spec_inspect_signature(self):
|
||||
|
||||
def myfunc(x, y):
|
||||
pass
|
||||
def myfunc(x, y): pass
|
||||
|
||||
mock = create_autospec(myfunc)
|
||||
mock(1, 2)
|
||||
|
@ -930,6 +929,7 @@ class SpecSignatureTest(unittest.TestCase):
|
|||
def foo(a: int, b: int=10, *, c:int) -> int:
|
||||
return a + b + c
|
||||
|
||||
self.assertEqual(foo(1, 2 , c=3), 6)
|
||||
mock = create_autospec(foo)
|
||||
mock(1, 2, c=3)
|
||||
mock(1, c=3)
|
||||
|
@ -940,6 +940,42 @@ class SpecSignatureTest(unittest.TestCase):
|
|||
self.assertRaises(TypeError, mock, 1, 2, 3, c=4)
|
||||
|
||||
|
||||
def test_spec_function_no_name(self):
|
||||
func = lambda: 'nope'
|
||||
mock = create_autospec(func)
|
||||
self.assertEqual(mock.__name__, 'funcopy')
|
||||
|
||||
|
||||
def test_spec_function_assert_has_calls(self):
|
||||
def f(a): pass
|
||||
mock = create_autospec(f)
|
||||
mock(1)
|
||||
mock.assert_has_calls([call(1)])
|
||||
with self.assertRaises(AssertionError):
|
||||
mock.assert_has_calls([call(2)])
|
||||
|
||||
|
||||
def test_spec_function_assert_any_call(self):
|
||||
def f(a): pass
|
||||
mock = create_autospec(f)
|
||||
mock(1)
|
||||
mock.assert_any_call(1)
|
||||
with self.assertRaises(AssertionError):
|
||||
mock.assert_any_call(2)
|
||||
|
||||
|
||||
def test_spec_function_reset_mock(self):
|
||||
def f(a): pass
|
||||
rv = Mock()
|
||||
mock = create_autospec(f, return_value=rv)
|
||||
mock(1)(2)
|
||||
self.assertEqual(mock.mock_calls, [call(1)])
|
||||
self.assertEqual(rv.mock_calls, [call(2)])
|
||||
mock.reset_mock()
|
||||
self.assertEqual(mock.mock_calls, [])
|
||||
self.assertEqual(rv.mock_calls, [])
|
||||
|
||||
|
||||
class TestCallList(unittest.TestCase):
|
||||
|
||||
def test_args_list_contains_call_list(self):
|
||||
|
@ -1019,16 +1055,14 @@ class TestCallablePredicate(unittest.TestCase):
|
|||
|
||||
def test_call_magic_method(self):
|
||||
class Callable:
|
||||
def __call__(self):
|
||||
pass
|
||||
def __call__(self): pass
|
||||
instance = Callable()
|
||||
self.assertTrue(_callable(instance))
|
||||
|
||||
def test_staticmethod(self):
|
||||
class WithStaticMethod:
|
||||
@staticmethod
|
||||
def staticfunc():
|
||||
pass
|
||||
def staticfunc(): pass
|
||||
self.assertTrue(_callable(WithStaticMethod.staticfunc))
|
||||
|
||||
def test_non_callable_staticmethod(self):
|
||||
|
@ -1039,8 +1073,7 @@ class TestCallablePredicate(unittest.TestCase):
|
|||
def test_classmethod(self):
|
||||
class WithClassMethod:
|
||||
@classmethod
|
||||
def classfunc(cls):
|
||||
pass
|
||||
def classfunc(cls): pass
|
||||
self.assertTrue(_callable(WithClassMethod.classfunc))
|
||||
|
||||
def test_non_callable_classmethod(self):
|
||||
|
|
|
@ -305,8 +305,7 @@ class TestMockingMagicMethods(unittest.TestCase):
|
|||
|
||||
def test_magic_methods_and_spec(self):
|
||||
class Iterable(object):
|
||||
def __iter__(self):
|
||||
pass
|
||||
def __iter__(self): pass
|
||||
|
||||
mock = Mock(spec=Iterable)
|
||||
self.assertRaises(AttributeError, lambda: mock.__iter__)
|
||||
|
@ -330,8 +329,7 @@ class TestMockingMagicMethods(unittest.TestCase):
|
|||
|
||||
def test_magic_methods_and_spec_set(self):
|
||||
class Iterable(object):
|
||||
def __iter__(self):
|
||||
pass
|
||||
def __iter__(self): pass
|
||||
|
||||
mock = Mock(spec_set=Iterable)
|
||||
self.assertRaises(AttributeError, lambda: mock.__iter__)
|
||||
|
|
|
@ -28,16 +28,13 @@ class Iter(object):
|
|||
|
||||
|
||||
class Something(object):
|
||||
def meth(self, a, b, c, d=None):
|
||||
pass
|
||||
def meth(self, a, b, c, d=None): pass
|
||||
|
||||
@classmethod
|
||||
def cmeth(cls, a, b, c, d=None):
|
||||
pass
|
||||
def cmeth(cls, a, b, c, d=None): pass
|
||||
|
||||
@staticmethod
|
||||
def smeth(a, b, c, d=None):
|
||||
pass
|
||||
def smeth(a, b, c, d=None): pass
|
||||
|
||||
|
||||
class MockTest(unittest.TestCase):
|
||||
|
@ -83,6 +80,21 @@ class MockTest(unittest.TestCase):
|
|||
"return value in constructor not honoured")
|
||||
|
||||
|
||||
def test_change_return_value_via_delegate(self):
|
||||
def f(): pass
|
||||
mock = create_autospec(f)
|
||||
mock.mock.return_value = 1
|
||||
self.assertEqual(mock(), 1)
|
||||
|
||||
|
||||
def test_change_side_effect_via_delegate(self):
|
||||
def f(): pass
|
||||
mock = create_autospec(f)
|
||||
mock.mock.side_effect = TypeError()
|
||||
with self.assertRaises(TypeError):
|
||||
mock()
|
||||
|
||||
|
||||
def test_repr(self):
|
||||
mock = Mock(name='foo')
|
||||
self.assertIn('foo', repr(mock))
|
||||
|
@ -161,8 +173,7 @@ class MockTest(unittest.TestCase):
|
|||
results = [1, 2, 3]
|
||||
def effect():
|
||||
return results.pop()
|
||||
def f():
|
||||
pass
|
||||
def f(): pass
|
||||
|
||||
mock = create_autospec(f)
|
||||
mock.side_effect = [1, 2, 3]
|
||||
|
@ -177,8 +188,7 @@ class MockTest(unittest.TestCase):
|
|||
|
||||
def test_autospec_side_effect_exception(self):
|
||||
# Test for issue 23661
|
||||
def f():
|
||||
pass
|
||||
def f(): pass
|
||||
|
||||
mock = create_autospec(f)
|
||||
mock.side_effect = ValueError('Bazinga!')
|
||||
|
@ -340,8 +350,7 @@ class MockTest(unittest.TestCase):
|
|||
|
||||
|
||||
def test_assert_called_with_function_spec(self):
|
||||
def f(a, b, c, d=None):
|
||||
pass
|
||||
def f(a, b, c, d=None): pass
|
||||
|
||||
mock = Mock(spec=f)
|
||||
|
||||
|
@ -409,8 +418,7 @@ class MockTest(unittest.TestCase):
|
|||
|
||||
|
||||
def test_assert_called_once_with_function_spec(self):
|
||||
def f(a, b, c, d=None):
|
||||
pass
|
||||
def f(a, b, c, d=None): pass
|
||||
|
||||
mock = Mock(spec=f)
|
||||
|
||||
|
@ -514,8 +522,7 @@ class MockTest(unittest.TestCase):
|
|||
class Something(object):
|
||||
x = 3
|
||||
__something__ = None
|
||||
def y(self):
|
||||
pass
|
||||
def y(self): pass
|
||||
|
||||
def test_attributes(mock):
|
||||
# should work
|
||||
|
@ -601,8 +608,7 @@ class MockTest(unittest.TestCase):
|
|||
|
||||
def test_customize_wrapped_object_with_side_effect_iterable(self):
|
||||
class Real(object):
|
||||
def method(self):
|
||||
raise NotImplementedError()
|
||||
def method(self): pass
|
||||
|
||||
real = Real()
|
||||
mock = Mock(wraps=real)
|
||||
|
@ -615,8 +621,7 @@ class MockTest(unittest.TestCase):
|
|||
|
||||
def test_customize_wrapped_object_with_side_effect_exception(self):
|
||||
class Real(object):
|
||||
def method(self):
|
||||
raise NotImplementedError()
|
||||
def method(self): pass
|
||||
|
||||
real = Real()
|
||||
mock = Mock(wraps=real)
|
||||
|
@ -627,9 +632,7 @@ class MockTest(unittest.TestCase):
|
|||
|
||||
def test_customize_wrapped_object_with_side_effect_function(self):
|
||||
class Real(object):
|
||||
def method(self):
|
||||
raise NotImplementedError()
|
||||
|
||||
def method(self): pass
|
||||
def side_effect():
|
||||
return sentinel.VALUE
|
||||
|
||||
|
@ -642,8 +645,7 @@ class MockTest(unittest.TestCase):
|
|||
|
||||
def test_customize_wrapped_object_with_return_value(self):
|
||||
class Real(object):
|
||||
def method(self):
|
||||
raise NotImplementedError()
|
||||
def method(self): pass
|
||||
|
||||
real = Real()
|
||||
mock = Mock(wraps=real)
|
||||
|
@ -655,8 +657,7 @@ class MockTest(unittest.TestCase):
|
|||
def test_customize_wrapped_object_with_return_value_and_side_effect(self):
|
||||
# side_effect should always take precedence over return_value.
|
||||
class Real(object):
|
||||
def method(self):
|
||||
raise NotImplementedError()
|
||||
def method(self): pass
|
||||
|
||||
real = Real()
|
||||
mock = Mock(wraps=real)
|
||||
|
@ -671,8 +672,7 @@ class MockTest(unittest.TestCase):
|
|||
def test_customize_wrapped_object_with_return_value_and_side_effect2(self):
|
||||
# side_effect can return DEFAULT to default to return_value
|
||||
class Real(object):
|
||||
def method(self):
|
||||
raise NotImplementedError()
|
||||
def method(self): pass
|
||||
|
||||
real = Real()
|
||||
mock = Mock(wraps=real)
|
||||
|
@ -684,8 +684,7 @@ class MockTest(unittest.TestCase):
|
|||
|
||||
def test_customize_wrapped_object_with_return_value_and_side_effect_default(self):
|
||||
class Real(object):
|
||||
def method(self):
|
||||
raise NotImplementedError()
|
||||
def method(self): pass
|
||||
|
||||
real = Real()
|
||||
mock = Mock(wraps=real)
|
||||
|
@ -764,6 +763,26 @@ class MockTest(unittest.TestCase):
|
|||
self.assertIsInstance(mock, X)
|
||||
|
||||
|
||||
def test_spec_class_no_object_base(self):
|
||||
class X:
|
||||
pass
|
||||
|
||||
mock = Mock(spec=X)
|
||||
self.assertIsInstance(mock, X)
|
||||
|
||||
mock = Mock(spec=X())
|
||||
self.assertIsInstance(mock, X)
|
||||
|
||||
self.assertIs(mock.__class__, X)
|
||||
self.assertEqual(Mock().__class__.__name__, 'Mock')
|
||||
|
||||
mock = Mock(spec_set=X)
|
||||
self.assertIsInstance(mock, X)
|
||||
|
||||
mock = Mock(spec_set=X())
|
||||
self.assertIsInstance(mock, X)
|
||||
|
||||
|
||||
def test_setting_attribute_with_spec_set(self):
|
||||
class X(object):
|
||||
y = 3
|
||||
|
@ -902,15 +921,9 @@ class MockTest(unittest.TestCase):
|
|||
|
||||
def assertRaisesWithMsg(self, exception, message, func, *args, **kwargs):
|
||||
# needed because assertRaisesRegex doesn't work easily with newlines
|
||||
try:
|
||||
with self.assertRaises(exception) as context:
|
||||
func(*args, **kwargs)
|
||||
except:
|
||||
instance = sys.exc_info()[1]
|
||||
self.assertIsInstance(instance, exception)
|
||||
else:
|
||||
self.fail('Exception %r not raised' % (exception,))
|
||||
|
||||
msg = str(instance)
|
||||
msg = str(context.exception)
|
||||
self.assertEqual(msg, message)
|
||||
|
||||
|
||||
|
@ -1099,6 +1112,18 @@ class MockTest(unittest.TestCase):
|
|||
self.assertEqual(repr(m.mock_calls[2]), 'call.foo().bar().baz.bob()')
|
||||
|
||||
|
||||
def test_mock_call_repr_loop(self):
|
||||
m = Mock()
|
||||
m.foo = m
|
||||
repr(m.foo())
|
||||
self.assertRegex(repr(m.foo()), r"<Mock name='mock\(\)' id='\d+'>")
|
||||
|
||||
|
||||
def test_mock_calls_contains(self):
|
||||
m = Mock()
|
||||
self.assertFalse([call()] in m.mock_calls)
|
||||
|
||||
|
||||
def test_subclassing(self):
|
||||
class Subclass(Mock):
|
||||
pass
|
||||
|
@ -1312,8 +1337,7 @@ class MockTest(unittest.TestCase):
|
|||
|
||||
|
||||
def test_assert_has_calls_with_function_spec(self):
|
||||
def f(a, b, c, d=None):
|
||||
pass
|
||||
def f(a, b, c, d=None): pass
|
||||
|
||||
mock = Mock(spec=f)
|
||||
|
||||
|
@ -1371,8 +1395,7 @@ class MockTest(unittest.TestCase):
|
|||
|
||||
|
||||
def test_assert_any_call_with_function_spec(self):
|
||||
def f(a, b, c, d=None):
|
||||
pass
|
||||
def f(a, b, c, d=None): pass
|
||||
|
||||
mock = Mock(spec=f)
|
||||
|
||||
|
@ -1391,8 +1414,7 @@ class MockTest(unittest.TestCase):
|
|||
|
||||
|
||||
def test_mock_calls_create_autospec(self):
|
||||
def f(a, b):
|
||||
pass
|
||||
def f(a, b): pass
|
||||
obj = Iter()
|
||||
obj.f = f
|
||||
|
||||
|
@ -1417,12 +1439,10 @@ class MockTest(unittest.TestCase):
|
|||
def test_create_autospec_classmethod_and_staticmethod(self):
|
||||
class TestClass:
|
||||
@classmethod
|
||||
def class_method(cls):
|
||||
pass
|
||||
def class_method(cls): pass
|
||||
|
||||
@staticmethod
|
||||
def static_method():
|
||||
pass
|
||||
def static_method(): pass
|
||||
for method in ('class_method', 'static_method'):
|
||||
with self.subTest(method=method):
|
||||
mock_method = mock.create_autospec(getattr(TestClass, method))
|
||||
|
@ -1848,8 +1868,7 @@ class MockTest(unittest.TestCase):
|
|||
|
||||
def test_parent_propagation_with_create_autospec(self):
|
||||
|
||||
def foo(a, b):
|
||||
pass
|
||||
def foo(a, b): pass
|
||||
|
||||
mock = Mock()
|
||||
mock.child = create_autospec(foo)
|
||||
|
@ -1878,11 +1897,12 @@ class MockTest(unittest.TestCase):
|
|||
with patch.dict('sys.modules'):
|
||||
del sys.modules['unittest.mock']
|
||||
|
||||
def trace(frame, event, arg):
|
||||
# This trace will stop coverage being measured ;-)
|
||||
def trace(frame, event, arg): # pragma: no cover
|
||||
return trace
|
||||
|
||||
self.addCleanup(sys.settrace, sys.gettrace())
|
||||
sys.settrace(trace)
|
||||
self.addCleanup(sys.settrace, None)
|
||||
|
||||
from unittest.mock import (
|
||||
Mock, MagicMock, NonCallableMock, NonCallableMagicMock
|
||||
|
|
|
@ -43,31 +43,24 @@ something_else = sentinel.SomethingElse
|
|||
|
||||
|
||||
class Foo(object):
|
||||
def __init__(self, a):
|
||||
pass
|
||||
def f(self, a):
|
||||
pass
|
||||
def g(self):
|
||||
pass
|
||||
def __init__(self, a): pass
|
||||
def f(self, a): pass
|
||||
def g(self): pass
|
||||
foo = 'bar'
|
||||
|
||||
@staticmethod
|
||||
def static_method():
|
||||
return 24
|
||||
def static_method(): pass
|
||||
|
||||
@classmethod
|
||||
def class_method(cls):
|
||||
return 42
|
||||
def class_method(cls): pass
|
||||
|
||||
class Bar(object):
|
||||
def a(self):
|
||||
pass
|
||||
def a(self): pass
|
||||
|
||||
foo_name = '%s.Foo' % __name__
|
||||
|
||||
|
||||
def function(a, b=Foo):
|
||||
pass
|
||||
def function(a, b=Foo): pass
|
||||
|
||||
|
||||
class Container(object):
|
||||
|
@ -370,31 +363,19 @@ class PatchTest(unittest.TestCase):
|
|||
|
||||
|
||||
def test_patch_wont_create_by_default(self):
|
||||
try:
|
||||
with self.assertRaises(AttributeError):
|
||||
@patch('%s.frooble' % builtin_string, sentinel.Frooble)
|
||||
def test():
|
||||
self.assertEqual(frooble, sentinel.Frooble)
|
||||
def test(): pass
|
||||
|
||||
test()
|
||||
except AttributeError:
|
||||
pass
|
||||
else:
|
||||
self.fail('Patching non existent attributes should fail')
|
||||
|
||||
self.assertRaises(NameError, lambda: frooble)
|
||||
|
||||
|
||||
def test_patchobject_wont_create_by_default(self):
|
||||
try:
|
||||
with self.assertRaises(AttributeError):
|
||||
@patch.object(SomeClass, 'ord', sentinel.Frooble)
|
||||
def test():
|
||||
self.fail('Patching non existent attributes should fail')
|
||||
|
||||
def test(): pass
|
||||
test()
|
||||
except AttributeError:
|
||||
pass
|
||||
else:
|
||||
self.fail('Patching non existent attributes should fail')
|
||||
self.assertFalse(hasattr(SomeClass, 'ord'))
|
||||
|
||||
|
||||
|
@ -484,6 +465,9 @@ class PatchTest(unittest.TestCase):
|
|||
attribute = sentinel.Original
|
||||
|
||||
class Foo(object):
|
||||
|
||||
test_class_attr = 'whatever'
|
||||
|
||||
def test_method(other_self, mock_something):
|
||||
self.assertEqual(PTModule.something, mock_something,
|
||||
"unpatched")
|
||||
|
@ -642,8 +626,7 @@ class PatchTest(unittest.TestCase):
|
|||
@patch('%s.SomeClass' % __name__, object(), autospec=True)
|
||||
@patch.object(SomeClass, object())
|
||||
@patch.dict(foo)
|
||||
def some_name():
|
||||
pass
|
||||
def some_name(): pass
|
||||
|
||||
self.assertEqual(some_name.__name__, 'some_name')
|
||||
|
||||
|
@ -654,12 +637,9 @@ class PatchTest(unittest.TestCase):
|
|||
@patch.dict(foo, {'a': 'b'})
|
||||
def test():
|
||||
raise NameError('Konrad')
|
||||
try:
|
||||
|
||||
with self.assertRaises(NameError):
|
||||
test()
|
||||
except NameError:
|
||||
pass
|
||||
else:
|
||||
self.fail('NameError not raised by test')
|
||||
|
||||
self.assertEqual(foo, {})
|
||||
|
||||
|
@ -689,49 +669,6 @@ class PatchTest(unittest.TestCase):
|
|||
support.target = original
|
||||
|
||||
|
||||
def test_patch_descriptor(self):
|
||||
# would be some effort to fix this - we could special case the
|
||||
# builtin descriptors: classmethod, property, staticmethod
|
||||
return
|
||||
class Nothing(object):
|
||||
foo = None
|
||||
|
||||
class Something(object):
|
||||
foo = {}
|
||||
|
||||
@patch.object(Nothing, 'foo', 2)
|
||||
@classmethod
|
||||
def klass(cls):
|
||||
self.assertIs(cls, Something)
|
||||
|
||||
@patch.object(Nothing, 'foo', 2)
|
||||
@staticmethod
|
||||
def static(arg):
|
||||
return arg
|
||||
|
||||
@patch.dict(foo)
|
||||
@classmethod
|
||||
def klass_dict(cls):
|
||||
self.assertIs(cls, Something)
|
||||
|
||||
@patch.dict(foo)
|
||||
@staticmethod
|
||||
def static_dict(arg):
|
||||
return arg
|
||||
|
||||
# these will raise exceptions if patching descriptors is broken
|
||||
self.assertEqual(Something.static('f00'), 'f00')
|
||||
Something.klass()
|
||||
self.assertEqual(Something.static_dict('f00'), 'f00')
|
||||
Something.klass_dict()
|
||||
|
||||
something = Something()
|
||||
self.assertEqual(something.static('f00'), 'f00')
|
||||
something.klass()
|
||||
self.assertEqual(something.static_dict('f00'), 'f00')
|
||||
something.klass_dict()
|
||||
|
||||
|
||||
def test_patch_spec_set(self):
|
||||
@patch('%s.SomeClass' % __name__, spec=SomeClass, spec_set=True)
|
||||
def test(MockClass):
|
||||
|
@ -931,17 +868,13 @@ class PatchTest(unittest.TestCase):
|
|||
|
||||
def test_autospec(self):
|
||||
class Boo(object):
|
||||
def __init__(self, a):
|
||||
pass
|
||||
def f(self, a):
|
||||
pass
|
||||
def g(self):
|
||||
pass
|
||||
def __init__(self, a): pass
|
||||
def f(self, a): pass
|
||||
def g(self): pass
|
||||
foo = 'bar'
|
||||
|
||||
class Bar(object):
|
||||
def a(self):
|
||||
pass
|
||||
def a(self): pass
|
||||
|
||||
def _test(mock):
|
||||
mock(1)
|
||||
|
@ -1488,20 +1421,17 @@ class PatchTest(unittest.TestCase):
|
|||
@patch.object(Foo, 'g', 1)
|
||||
@patch.object(Foo, 'missing', 1)
|
||||
@patch.object(Foo, 'f', 1)
|
||||
def thing1():
|
||||
pass
|
||||
def thing1(): pass
|
||||
|
||||
@patch.object(Foo, 'missing', 1)
|
||||
@patch.object(Foo, 'g', 1)
|
||||
@patch.object(Foo, 'f', 1)
|
||||
def thing2():
|
||||
pass
|
||||
def thing2(): pass
|
||||
|
||||
@patch.object(Foo, 'g', 1)
|
||||
@patch.object(Foo, 'f', 1)
|
||||
@patch.object(Foo, 'missing', 1)
|
||||
def thing3():
|
||||
pass
|
||||
def thing3(): pass
|
||||
|
||||
for func in thing1, thing2, thing3:
|
||||
self.assertRaises(AttributeError, func)
|
||||
|
@ -1520,20 +1450,17 @@ class PatchTest(unittest.TestCase):
|
|||
@patch.object(Foo, 'g', 1)
|
||||
@patch.object(Foo, 'foo', new_callable=crasher)
|
||||
@patch.object(Foo, 'f', 1)
|
||||
def thing1():
|
||||
pass
|
||||
def thing1(): pass
|
||||
|
||||
@patch.object(Foo, 'foo', new_callable=crasher)
|
||||
@patch.object(Foo, 'g', 1)
|
||||
@patch.object(Foo, 'f', 1)
|
||||
def thing2():
|
||||
pass
|
||||
def thing2(): pass
|
||||
|
||||
@patch.object(Foo, 'g', 1)
|
||||
@patch.object(Foo, 'f', 1)
|
||||
@patch.object(Foo, 'foo', new_callable=crasher)
|
||||
def thing3():
|
||||
pass
|
||||
def thing3(): pass
|
||||
|
||||
for func in thing1, thing2, thing3:
|
||||
self.assertRaises(NameError, func)
|
||||
|
@ -1559,8 +1486,7 @@ class PatchTest(unittest.TestCase):
|
|||
patcher.additional_patchers = additionals
|
||||
|
||||
@patcher
|
||||
def func():
|
||||
pass
|
||||
def func(): pass
|
||||
|
||||
self.assertRaises(AttributeError, func)
|
||||
self.assertEqual(Foo.f, original_f)
|
||||
|
@ -1588,8 +1514,7 @@ class PatchTest(unittest.TestCase):
|
|||
patcher.additional_patchers = additionals
|
||||
|
||||
@patcher
|
||||
def func():
|
||||
pass
|
||||
def func(): pass
|
||||
|
||||
self.assertRaises(NameError, func)
|
||||
self.assertEqual(Foo.f, original_f)
|
||||
|
@ -1898,5 +1823,36 @@ class PatchTest(unittest.TestCase):
|
|||
self.assertEqual(foo(), 1)
|
||||
self.assertEqual(foo(), 0)
|
||||
|
||||
def test_dotted_but_module_not_loaded(self):
|
||||
# This exercises the AttributeError branch of _dot_lookup.
|
||||
|
||||
# make sure it's there
|
||||
import unittest.test.testmock.support
|
||||
# now make sure it's not:
|
||||
with patch.dict('sys.modules'):
|
||||
del sys.modules['unittest.test.testmock.support']
|
||||
del sys.modules['unittest.test.testmock']
|
||||
del sys.modules['unittest.test']
|
||||
del sys.modules['unittest']
|
||||
|
||||
# now make sure we can patch based on a dotted path:
|
||||
@patch('unittest.test.testmock.support.X')
|
||||
def test(mock):
|
||||
pass
|
||||
test()
|
||||
|
||||
|
||||
def test_invalid_target(self):
|
||||
with self.assertRaises(TypeError):
|
||||
patch('')
|
||||
|
||||
|
||||
def test_cant_set_kwargs_when_passing_a_mock(self):
|
||||
@patch('unittest.test.testmock.support.X', new=object(), x=1)
|
||||
def test(): pass
|
||||
with self.assertRaises(TypeError):
|
||||
test()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
|
|
|
@ -3,15 +3,10 @@ from unittest import mock
|
|||
|
||||
|
||||
class SampleObject:
|
||||
def __init__(self):
|
||||
self.attr_sample1 = 1
|
||||
self.attr_sample2 = 1
|
||||
|
||||
def method_sample1(self):
|
||||
pass
|
||||
def method_sample1(self): pass
|
||||
|
||||
def method_sample2(self):
|
||||
pass
|
||||
def method_sample2(self): pass
|
||||
|
||||
|
||||
class TestSealable(unittest.TestCase):
|
||||
|
|
|
@ -10,6 +10,8 @@ something = sentinel.Something
|
|||
something_else = sentinel.SomethingElse
|
||||
|
||||
|
||||
class SampleException(Exception): pass
|
||||
|
||||
|
||||
class WithTest(unittest.TestCase):
|
||||
|
||||
|
@ -20,14 +22,10 @@ class WithTest(unittest.TestCase):
|
|||
|
||||
|
||||
def test_with_statement_exception(self):
|
||||
try:
|
||||
with self.assertRaises(SampleException):
|
||||
with patch('%s.something' % __name__, sentinel.Something2):
|
||||
self.assertEqual(something, sentinel.Something2, "unpatched")
|
||||
raise Exception('pow')
|
||||
except Exception:
|
||||
pass
|
||||
else:
|
||||
self.fail("patch swallowed exception")
|
||||
raise SampleException()
|
||||
self.assertEqual(something, sentinel.Something)
|
||||
|
||||
|
||||
|
@ -128,8 +126,7 @@ class WithTest(unittest.TestCase):
|
|||
|
||||
def test_double_patch_instance_method(self):
|
||||
class C:
|
||||
def f(self):
|
||||
pass
|
||||
def f(self): pass
|
||||
|
||||
c = C()
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue