Commit adbf178e authored by Chris Withers's avatar Chris Withers Committed by GitHub

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.
parent b7378d77
...@@ -63,10 +63,7 @@ def _get_signature_object(func, as_instance, eat_self): ...@@ -63,10 +63,7 @@ def _get_signature_object(func, as_instance, eat_self):
""" """
if isinstance(func, type) and not as_instance: if isinstance(func, type) and not as_instance:
# If it's a type and should be modelled as a type, use __init__. # If it's a type and should be modelled as a type, use __init__.
try: func = func.__init__
func = func.__init__
except AttributeError:
return None
# Skip the `self` argument in __init__ # Skip the `self` argument in __init__
eat_self = True eat_self = True
elif not isinstance(func, FunctionTypes): elif not isinstance(func, FunctionTypes):
...@@ -147,8 +144,6 @@ def _set_signature(mock, original, instance=False): ...@@ -147,8 +144,6 @@ def _set_signature(mock, original, instance=False):
# creates a function with signature (*args, **kwargs) that delegates to a # creates a function with signature (*args, **kwargs) that delegates to a
# mock. It still does signature checking by calling a lambda with the same # mock. It still does signature checking by calling a lambda with the same
# signature as the original. # signature as the original.
if not _callable(original):
return
skipfirst = isinstance(original, type) skipfirst = isinstance(original, type)
result = _get_signature_object(original, instance, skipfirst) result = _get_signature_object(original, instance, skipfirst)
...@@ -175,10 +170,6 @@ def _set_signature(mock, original, instance=False): ...@@ -175,10 +170,6 @@ def _set_signature(mock, original, instance=False):
def _setup_func(funcopy, mock, sig): def _setup_func(funcopy, mock, sig):
funcopy.mock = mock funcopy.mock = mock
# can't use isinstance with mocks
if not _is_instance_mock(mock):
return
def assert_called_with(*args, **kwargs): def assert_called_with(*args, **kwargs):
return mock.assert_called_with(*args, **kwargs) return mock.assert_called_with(*args, **kwargs)
def assert_called(*args, **kwargs): def assert_called(*args, **kwargs):
...@@ -263,12 +254,6 @@ _missing = sentinel.MISSING ...@@ -263,12 +254,6 @@ _missing = sentinel.MISSING
_deleted = sentinel.DELETED _deleted = sentinel.DELETED
def _copy(value):
if type(value) in (dict, list, tuple, set):
return type(value)(value)
return value
_allowed_names = { _allowed_names = {
'return_value', '_mock_return_value', 'side_effect', 'return_value', '_mock_return_value', 'side_effect',
'_mock_side_effect', '_mock_parent', '_mock_new_parent', '_mock_side_effect', '_mock_parent', '_mock_new_parent',
...@@ -351,8 +336,6 @@ def _check_and_set_parent(parent, value, name, new_name): ...@@ -351,8 +336,6 @@ def _check_and_set_parent(parent, value, name, new_name):
class _MockIter(object): class _MockIter(object):
def __init__(self, obj): def __init__(self, obj):
self.obj = iter(obj) self.obj = iter(obj)
def __iter__(self):
return self
def __next__(self): def __next__(self):
return next(self.obj) return next(self.obj)
...@@ -452,7 +435,7 @@ class NonCallableMock(Base): ...@@ -452,7 +435,7 @@ class NonCallableMock(Base):
if isinstance(spec, type): if isinstance(spec, type):
_spec_class = spec _spec_class = spec
else: else:
_spec_class = _get_class(spec) _spec_class = type(spec)
res = _get_signature_object(spec, res = _get_signature_object(spec,
_spec_as_instance, _eat_self) _spec_as_instance, _eat_self)
_spec_signature = res and res[1] _spec_signature = res and res[1]
...@@ -624,7 +607,7 @@ class NonCallableMock(Base): ...@@ -624,7 +607,7 @@ class NonCallableMock(Base):
dot = '.' dot = '.'
if _name_list == ['()']: if _name_list == ['()']:
dot = '' dot = ''
seen = set()
while _parent is not None: while _parent is not None:
last = _parent last = _parent
...@@ -635,11 +618,6 @@ class NonCallableMock(Base): ...@@ -635,11 +618,6 @@ class NonCallableMock(Base):
_parent = _parent._mock_new_parent _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)) _name_list = list(reversed(_name_list))
_first = last._mock_name or 'mock' _first = last._mock_name or 'mock'
if len(_name_list) > 1: if len(_name_list) > 1:
...@@ -753,8 +731,6 @@ class NonCallableMock(Base): ...@@ -753,8 +731,6 @@ class NonCallableMock(Base):
message = 'expected call not found.\nExpected: %s\nActual: %s' message = 'expected call not found.\nExpected: %s\nActual: %s'
expected_string = self._format_mock_call_signature(args, kwargs) expected_string = self._format_mock_call_signature(args, kwargs)
call_args = self.call_args call_args = self.call_args
if len(call_args) == 3:
call_args = call_args[1:]
actual_string = self._format_mock_call_signature(*call_args) actual_string = self._format_mock_call_signature(*call_args)
return message % (expected_string, actual_string) return message % (expected_string, actual_string)
...@@ -992,8 +968,6 @@ class CallableMixin(Base): ...@@ -992,8 +968,6 @@ class CallableMixin(Base):
self.call_args = _call self.call_args = _call
self.call_args_list.append(_call) self.call_args_list.append(_call)
seen = set()
# initial stuff for method_calls: # initial stuff for method_calls:
do_method_calls = self._mock_parent is not None do_method_calls = self._mock_parent is not None
method_call_name = self._mock_name method_call_name = self._mock_name
...@@ -1029,13 +1003,6 @@ class CallableMixin(Base): ...@@ -1029,13 +1003,6 @@ class CallableMixin(Base):
# follow the parental chain: # follow the parental chain:
_new_parent = _new_parent._mock_new_parent _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 effect = self.side_effect
if effect is not None: if effect is not None:
if _is_exception(effect): if _is_exception(effect):
...@@ -1858,12 +1825,7 @@ def _set_return_value(mock, method, name): ...@@ -1858,12 +1825,7 @@ def _set_return_value(mock, method, name):
return_calulator = _calculate_return_value.get(name) return_calulator = _calculate_return_value.get(name)
if return_calulator is not None: if return_calulator is not None:
try: return_value = return_calulator(mock)
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)
method.return_value = return_value method.return_value = return_value
return return
...@@ -1943,10 +1905,6 @@ class MagicProxy(object): ...@@ -1943,10 +1905,6 @@ class MagicProxy(object):
self.name = name self.name = name
self.parent = parent self.parent = parent
def __call__(self, *args, **kwargs):
m = self.create_mock()
return m(*args, **kwargs)
def create_mock(self): def create_mock(self):
entry = self.name entry = self.name
parent = self.parent parent = self.parent
...@@ -2330,19 +2288,10 @@ def _must_skip(spec, entry, is_type): ...@@ -2330,19 +2288,10 @@ def _must_skip(spec, entry, is_type):
else: else:
return False return False
# shouldn't get here unless function is a dynamically provided attribute # function is a dynamically provided attribute
# XXXX untested behaviour
return is_type 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): class _SpecState(object):
def __init__(self, spec, spec_set=False, parent=None, def __init__(self, spec, spec_set=False, parent=None,
......
...@@ -9,8 +9,7 @@ def is_instance(obj, klass): ...@@ -9,8 +9,7 @@ def is_instance(obj, klass):
class SomeClass(object): class SomeClass(object):
class_attribute = None class_attribute = None
def wibble(self): def wibble(self): pass
pass
class X(object): class X(object):
......
...@@ -98,8 +98,7 @@ class TestCallable(unittest.TestCase): ...@@ -98,8 +98,7 @@ class TestCallable(unittest.TestCase):
def test_patch_spec_callable_class(self): def test_patch_spec_callable_class(self):
class CallableX(X): class CallableX(X):
def __call__(self): def __call__(self): pass
pass
class Sub(CallableX): class Sub(CallableX):
pass pass
......
This diff is collapsed.
...@@ -305,8 +305,7 @@ class TestMockingMagicMethods(unittest.TestCase): ...@@ -305,8 +305,7 @@ class TestMockingMagicMethods(unittest.TestCase):
def test_magic_methods_and_spec(self): def test_magic_methods_and_spec(self):
class Iterable(object): class Iterable(object):
def __iter__(self): def __iter__(self): pass
pass
mock = Mock(spec=Iterable) mock = Mock(spec=Iterable)
self.assertRaises(AttributeError, lambda: mock.__iter__) self.assertRaises(AttributeError, lambda: mock.__iter__)
...@@ -330,8 +329,7 @@ class TestMockingMagicMethods(unittest.TestCase): ...@@ -330,8 +329,7 @@ class TestMockingMagicMethods(unittest.TestCase):
def test_magic_methods_and_spec_set(self): def test_magic_methods_and_spec_set(self):
class Iterable(object): class Iterable(object):
def __iter__(self): def __iter__(self): pass
pass
mock = Mock(spec_set=Iterable) mock = Mock(spec_set=Iterable)
self.assertRaises(AttributeError, lambda: mock.__iter__) self.assertRaises(AttributeError, lambda: mock.__iter__)
......
...@@ -28,16 +28,13 @@ class Iter(object): ...@@ -28,16 +28,13 @@ class Iter(object):
class Something(object): class Something(object):
def meth(self, a, b, c, d=None): def meth(self, a, b, c, d=None): pass
pass
@classmethod @classmethod
def cmeth(cls, a, b, c, d=None): def cmeth(cls, a, b, c, d=None): pass
pass
@staticmethod @staticmethod
def smeth(a, b, c, d=None): def smeth(a, b, c, d=None): pass
pass
class MockTest(unittest.TestCase): class MockTest(unittest.TestCase):
...@@ -83,6 +80,21 @@ class MockTest(unittest.TestCase): ...@@ -83,6 +80,21 @@ class MockTest(unittest.TestCase):
"return value in constructor not honoured") "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): def test_repr(self):
mock = Mock(name='foo') mock = Mock(name='foo')
self.assertIn('foo', repr(mock)) self.assertIn('foo', repr(mock))
...@@ -161,8 +173,7 @@ class MockTest(unittest.TestCase): ...@@ -161,8 +173,7 @@ class MockTest(unittest.TestCase):
results = [1, 2, 3] results = [1, 2, 3]
def effect(): def effect():
return results.pop() return results.pop()
def f(): def f(): pass
pass
mock = create_autospec(f) mock = create_autospec(f)
mock.side_effect = [1, 2, 3] mock.side_effect = [1, 2, 3]
...@@ -177,8 +188,7 @@ class MockTest(unittest.TestCase): ...@@ -177,8 +188,7 @@ class MockTest(unittest.TestCase):
def test_autospec_side_effect_exception(self): def test_autospec_side_effect_exception(self):
# Test for issue 23661 # Test for issue 23661
def f(): def f(): pass
pass
mock = create_autospec(f) mock = create_autospec(f)
mock.side_effect = ValueError('Bazinga!') mock.side_effect = ValueError('Bazinga!')
...@@ -340,8 +350,7 @@ class MockTest(unittest.TestCase): ...@@ -340,8 +350,7 @@ class MockTest(unittest.TestCase):
def test_assert_called_with_function_spec(self): def test_assert_called_with_function_spec(self):
def f(a, b, c, d=None): def f(a, b, c, d=None): pass
pass
mock = Mock(spec=f) mock = Mock(spec=f)
...@@ -409,8 +418,7 @@ class MockTest(unittest.TestCase): ...@@ -409,8 +418,7 @@ class MockTest(unittest.TestCase):
def test_assert_called_once_with_function_spec(self): def test_assert_called_once_with_function_spec(self):
def f(a, b, c, d=None): def f(a, b, c, d=None): pass
pass
mock = Mock(spec=f) mock = Mock(spec=f)
...@@ -514,8 +522,7 @@ class MockTest(unittest.TestCase): ...@@ -514,8 +522,7 @@ class MockTest(unittest.TestCase):
class Something(object): class Something(object):
x = 3 x = 3
__something__ = None __something__ = None
def y(self): def y(self): pass
pass
def test_attributes(mock): def test_attributes(mock):
# should work # should work
...@@ -601,8 +608,7 @@ class MockTest(unittest.TestCase): ...@@ -601,8 +608,7 @@ class MockTest(unittest.TestCase):
def test_customize_wrapped_object_with_side_effect_iterable(self): def test_customize_wrapped_object_with_side_effect_iterable(self):
class Real(object): class Real(object):
def method(self): def method(self): pass
raise NotImplementedError()
real = Real() real = Real()
mock = Mock(wraps=real) mock = Mock(wraps=real)
...@@ -615,8 +621,7 @@ class MockTest(unittest.TestCase): ...@@ -615,8 +621,7 @@ class MockTest(unittest.TestCase):
def test_customize_wrapped_object_with_side_effect_exception(self): def test_customize_wrapped_object_with_side_effect_exception(self):
class Real(object): class Real(object):
def method(self): def method(self): pass
raise NotImplementedError()
real = Real() real = Real()
mock = Mock(wraps=real) mock = Mock(wraps=real)
...@@ -627,9 +632,7 @@ class MockTest(unittest.TestCase): ...@@ -627,9 +632,7 @@ class MockTest(unittest.TestCase):
def test_customize_wrapped_object_with_side_effect_function(self): def test_customize_wrapped_object_with_side_effect_function(self):
class Real(object): class Real(object):
def method(self): def method(self): pass
raise NotImplementedError()
def side_effect(): def side_effect():
return sentinel.VALUE return sentinel.VALUE
...@@ -642,8 +645,7 @@ class MockTest(unittest.TestCase): ...@@ -642,8 +645,7 @@ class MockTest(unittest.TestCase):
def test_customize_wrapped_object_with_return_value(self): def test_customize_wrapped_object_with_return_value(self):
class Real(object): class Real(object):
def method(self): def method(self): pass
raise NotImplementedError()
real = Real() real = Real()
mock = Mock(wraps=real) mock = Mock(wraps=real)
...@@ -655,8 +657,7 @@ class MockTest(unittest.TestCase): ...@@ -655,8 +657,7 @@ class MockTest(unittest.TestCase):
def test_customize_wrapped_object_with_return_value_and_side_effect(self): def test_customize_wrapped_object_with_return_value_and_side_effect(self):
# side_effect should always take precedence over return_value. # side_effect should always take precedence over return_value.
class Real(object): class Real(object):
def method(self): def method(self): pass
raise NotImplementedError()
real = Real() real = Real()
mock = Mock(wraps=real) mock = Mock(wraps=real)
...@@ -671,8 +672,7 @@ class MockTest(unittest.TestCase): ...@@ -671,8 +672,7 @@ class MockTest(unittest.TestCase):
def test_customize_wrapped_object_with_return_value_and_side_effect2(self): def test_customize_wrapped_object_with_return_value_and_side_effect2(self):
# side_effect can return DEFAULT to default to return_value # side_effect can return DEFAULT to default to return_value
class Real(object): class Real(object):
def method(self): def method(self): pass
raise NotImplementedError()
real = Real() real = Real()
mock = Mock(wraps=real) mock = Mock(wraps=real)
...@@ -684,8 +684,7 @@ class MockTest(unittest.TestCase): ...@@ -684,8 +684,7 @@ class MockTest(unittest.TestCase):
def test_customize_wrapped_object_with_return_value_and_side_effect_default(self): def test_customize_wrapped_object_with_return_value_and_side_effect_default(self):
class Real(object): class Real(object):
def method(self): def method(self): pass
raise NotImplementedError()
real = Real() real = Real()
mock = Mock(wraps=real) mock = Mock(wraps=real)
...@@ -764,6 +763,26 @@ class MockTest(unittest.TestCase): ...@@ -764,6 +763,26 @@ class MockTest(unittest.TestCase):
self.assertIsInstance(mock, X) 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): def test_setting_attribute_with_spec_set(self):
class X(object): class X(object):
y = 3 y = 3
...@@ -902,15 +921,9 @@ class MockTest(unittest.TestCase): ...@@ -902,15 +921,9 @@ class MockTest(unittest.TestCase):
def assertRaisesWithMsg(self, exception, message, func, *args, **kwargs): def assertRaisesWithMsg(self, exception, message, func, *args, **kwargs):
# needed because assertRaisesRegex doesn't work easily with newlines # needed because assertRaisesRegex doesn't work easily with newlines
try: with self.assertRaises(exception) as context:
func(*args, **kwargs) func(*args, **kwargs)
except: msg = str(context.exception)
instance = sys.exc_info()[1]
self.assertIsInstance(instance, exception)
else:
self.fail('Exception %r not raised' % (exception,))
msg = str(instance)
self.assertEqual(msg, message) self.assertEqual(msg, message)
...@@ -1099,6 +1112,18 @@ class MockTest(unittest.TestCase): ...@@ -1099,6 +1112,18 @@ class MockTest(unittest.TestCase):
self.assertEqual(repr(m.mock_calls[2]), 'call.foo().bar().baz.bob()') 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): def test_subclassing(self):
class Subclass(Mock): class Subclass(Mock):
pass pass
...@@ -1312,8 +1337,7 @@ class MockTest(unittest.TestCase): ...@@ -1312,8 +1337,7 @@ class MockTest(unittest.TestCase):
def test_assert_has_calls_with_function_spec(self): def test_assert_has_calls_with_function_spec(self):
def f(a, b, c, d=None): def f(a, b, c, d=None): pass
pass
mock = Mock(spec=f) mock = Mock(spec=f)
...@@ -1371,8 +1395,7 @@ class MockTest(unittest.TestCase): ...@@ -1371,8 +1395,7 @@ class MockTest(unittest.TestCase):
def test_assert_any_call_with_function_spec(self): def test_assert_any_call_with_function_spec(self):
def f(a, b, c, d=None): def f(a, b, c, d=None): pass
pass
mock = Mock(spec=f) mock = Mock(spec=f)
...@@ -1391,8 +1414,7 @@ class MockTest(unittest.TestCase): ...@@ -1391,8 +1414,7 @@ class MockTest(unittest.TestCase):
def test_mock_calls_create_autospec(self): def test_mock_calls_create_autospec(self):
def f(a, b): def f(a, b): pass
pass
obj = Iter() obj = Iter()
obj.f = f obj.f = f
...@@ -1417,12 +1439,10 @@ class MockTest(unittest.TestCase): ...@@ -1417,12 +1439,10 @@ class MockTest(unittest.TestCase):
def test_create_autospec_classmethod_and_staticmethod(self): def test_create_autospec_classmethod_and_staticmethod(self):
class TestClass: class TestClass:
@classmethod @classmethod
def class_method(cls): def class_method(cls): pass
pass
@staticmethod @staticmethod
def static_method(): def static_method(): pass
pass
for method in ('class_method', 'static_method'): for method in ('class_method', 'static_method'):
with self.subTest(method=method): with self.subTest(method=method):
mock_method = mock.create_autospec(getattr(TestClass, method)) mock_method = mock.create_autospec(getattr(TestClass, method))
...@@ -1848,8 +1868,7 @@ class MockTest(unittest.TestCase): ...@@ -1848,8 +1868,7 @@ class MockTest(unittest.TestCase):
def test_parent_propagation_with_create_autospec(self): def test_parent_propagation_with_create_autospec(self):
def foo(a, b): def foo(a, b): pass
pass
mock = Mock() mock = Mock()
mock.child = create_autospec(foo) mock.child = create_autospec(foo)
...@@ -1878,11 +1897,12 @@ class MockTest(unittest.TestCase): ...@@ -1878,11 +1897,12 @@ class MockTest(unittest.TestCase):
with patch.dict('sys.modules'): with patch.dict('sys.modules'):
del sys.modules['unittest.mock'] 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 return trace
self.addCleanup(sys.settrace, sys.gettrace())
sys.settrace(trace) sys.settrace(trace)
self.addCleanup(sys.settrace, None)
from unittest.mock import ( from unittest.mock import (
Mock, MagicMock, NonCallableMock, NonCallableMagicMock Mock, MagicMock, NonCallableMock, NonCallableMagicMock
......
...@@ -43,31 +43,24 @@ something_else = sentinel.SomethingElse ...@@ -43,31 +43,24 @@ something_else = sentinel.SomethingElse
class Foo(object): class Foo(object):
def __init__(self, a): def __init__(self, a): pass
pass def f(self, a): pass
def f(self, a): def g(self): pass
pass
def g(self):
pass
foo = 'bar' foo = 'bar'
@staticmethod @staticmethod
def static_method(): def static_method(): pass
return 24
@classmethod @classmethod
def class_method(cls): def class_method(cls): pass
return 42
class Bar(object): class Bar(object):
def a(self): def a(self): pass
pass
foo_name = '%s.Foo' % __name__ foo_name = '%s.Foo' % __name__
def function(a, b=Foo): def function(a, b=Foo): pass
pass
class Container(object): class Container(object):
...@@ -370,31 +363,19 @@ class PatchTest(unittest.TestCase): ...@@ -370,31 +363,19 @@ class PatchTest(unittest.TestCase):
def test_patch_wont_create_by_default(self): def test_patch_wont_create_by_default(self):
try: with self.assertRaises(AttributeError):
@patch('%s.frooble' % builtin_string, sentinel.Frooble) @patch('%s.frooble' % builtin_string, sentinel.Frooble)
def test(): def test(): pass
self.assertEqual(frooble, sentinel.Frooble)
test() test()
except AttributeError:
pass
else:
self.fail('Patching non existent attributes should fail')
self.assertRaises(NameError, lambda: frooble) self.assertRaises(NameError, lambda: frooble)
def test_patchobject_wont_create_by_default(self): def test_patchobject_wont_create_by_default(self):
try: with self.assertRaises(AttributeError):
@patch.object(SomeClass, 'ord', sentinel.Frooble) @patch.object(SomeClass, 'ord', sentinel.Frooble)
def test(): def test(): pass
self.fail('Patching non existent attributes should fail')
test() test()
except AttributeError:
pass
else:
self.fail('Patching non existent attributes should fail')
self.assertFalse(hasattr(SomeClass, 'ord')) self.assertFalse(hasattr(SomeClass, 'ord'))
...@@ -484,6 +465,9 @@ class PatchTest(unittest.TestCase): ...@@ -484,6 +465,9 @@ class PatchTest(unittest.TestCase):
attribute = sentinel.Original attribute = sentinel.Original
class Foo(object): class Foo(object):
test_class_attr = 'whatever'
def test_method(other_self, mock_something): def test_method(other_self, mock_something):
self.assertEqual(PTModule.something, mock_something, self.assertEqual(PTModule.something, mock_something,
"unpatched") "unpatched")
...@@ -642,8 +626,7 @@ class PatchTest(unittest.TestCase): ...@@ -642,8 +626,7 @@ class PatchTest(unittest.TestCase):
@patch('%s.SomeClass' % __name__, object(), autospec=True) @patch('%s.SomeClass' % __name__, object(), autospec=True)
@patch.object(SomeClass, object()) @patch.object(SomeClass, object())
@patch.dict(foo) @patch.dict(foo)
def some_name(): def some_name(): pass
pass
self.assertEqual(some_name.__name__, 'some_name') self.assertEqual(some_name.__name__, 'some_name')
...@@ -654,12 +637,9 @@ class PatchTest(unittest.TestCase): ...@@ -654,12 +637,9 @@ class PatchTest(unittest.TestCase):
@patch.dict(foo, {'a': 'b'}) @patch.dict(foo, {'a': 'b'})
def test(): def test():
raise NameError('Konrad') raise NameError('Konrad')
try:
with self.assertRaises(NameError):
test() test()
except NameError:
pass
else:
self.fail('NameError not raised by test')
self.assertEqual(foo, {}) self.assertEqual(foo, {})
...@@ -689,49 +669,6 @@ class PatchTest(unittest.TestCase): ...@@ -689,49 +669,6 @@ class PatchTest(unittest.TestCase):
support.target = original 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): def test_patch_spec_set(self):
@patch('%s.SomeClass' % __name__, spec=SomeClass, spec_set=True) @patch('%s.SomeClass' % __name__, spec=SomeClass, spec_set=True)
def test(MockClass): def test(MockClass):
...@@ -931,17 +868,13 @@ class PatchTest(unittest.TestCase): ...@@ -931,17 +868,13 @@ class PatchTest(unittest.TestCase):
def test_autospec(self): def test_autospec(self):
class Boo(object): class Boo(object):
def __init__(self, a): def __init__(self, a): pass
pass def f(self, a): pass
def f(self, a): def g(self): pass
pass
def g(self):
pass
foo = 'bar' foo = 'bar'
class Bar(object): class Bar(object):
def a(self): def a(self): pass
pass
def _test(mock): def _test(mock):
mock(1) mock(1)
...@@ -1488,20 +1421,17 @@ class PatchTest(unittest.TestCase): ...@@ -1488,20 +1421,17 @@ class PatchTest(unittest.TestCase):
@patch.object(Foo, 'g', 1) @patch.object(Foo, 'g', 1)
@patch.object(Foo, 'missing', 1) @patch.object(Foo, 'missing', 1)
@patch.object(Foo, 'f', 1) @patch.object(Foo, 'f', 1)
def thing1(): def thing1(): pass
pass
@patch.object(Foo, 'missing', 1) @patch.object(Foo, 'missing', 1)
@patch.object(Foo, 'g', 1) @patch.object(Foo, 'g', 1)
@patch.object(Foo, 'f', 1) @patch.object(Foo, 'f', 1)
def thing2(): def thing2(): pass
pass
@patch.object(Foo, 'g', 1) @patch.object(Foo, 'g', 1)
@patch.object(Foo, 'f', 1) @patch.object(Foo, 'f', 1)
@patch.object(Foo, 'missing', 1) @patch.object(Foo, 'missing', 1)
def thing3(): def thing3(): pass
pass
for func in thing1, thing2, thing3: for func in thing1, thing2, thing3:
self.assertRaises(AttributeError, func) self.assertRaises(AttributeError, func)
...@@ -1520,20 +1450,17 @@ class PatchTest(unittest.TestCase): ...@@ -1520,20 +1450,17 @@ class PatchTest(unittest.TestCase):
@patch.object(Foo, 'g', 1) @patch.object(Foo, 'g', 1)
@patch.object(Foo, 'foo', new_callable=crasher) @patch.object(Foo, 'foo', new_callable=crasher)
@patch.object(Foo, 'f', 1) @patch.object(Foo, 'f', 1)
def thing1(): def thing1(): pass
pass
@patch.object(Foo, 'foo', new_callable=crasher) @patch.object(Foo, 'foo', new_callable=crasher)
@patch.object(Foo, 'g', 1) @patch.object(Foo, 'g', 1)
@patch.object(Foo, 'f', 1) @patch.object(Foo, 'f', 1)
def thing2(): def thing2(): pass
pass
@patch.object(Foo, 'g', 1) @patch.object(Foo, 'g', 1)
@patch.object(Foo, 'f', 1) @patch.object(Foo, 'f', 1)
@patch.object(Foo, 'foo', new_callable=crasher) @patch.object(Foo, 'foo', new_callable=crasher)
def thing3(): def thing3(): pass
pass
for func in thing1, thing2, thing3: for func in thing1, thing2, thing3:
self.assertRaises(NameError, func) self.assertRaises(NameError, func)
...@@ -1559,8 +1486,7 @@ class PatchTest(unittest.TestCase): ...@@ -1559,8 +1486,7 @@ class PatchTest(unittest.TestCase):
patcher.additional_patchers = additionals patcher.additional_patchers = additionals
@patcher @patcher
def func(): def func(): pass
pass
self.assertRaises(AttributeError, func) self.assertRaises(AttributeError, func)
self.assertEqual(Foo.f, original_f) self.assertEqual(Foo.f, original_f)
...@@ -1588,8 +1514,7 @@ class PatchTest(unittest.TestCase): ...@@ -1588,8 +1514,7 @@ class PatchTest(unittest.TestCase):
patcher.additional_patchers = additionals patcher.additional_patchers = additionals
@patcher @patcher
def func(): def func(): pass
pass
self.assertRaises(NameError, func) self.assertRaises(NameError, func)
self.assertEqual(Foo.f, original_f) self.assertEqual(Foo.f, original_f)
...@@ -1898,5 +1823,36 @@ class PatchTest(unittest.TestCase): ...@@ -1898,5 +1823,36 @@ class PatchTest(unittest.TestCase):
self.assertEqual(foo(), 1) self.assertEqual(foo(), 1)
self.assertEqual(foo(), 0) 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__': if __name__ == '__main__':
unittest.main() unittest.main()
...@@ -3,15 +3,10 @@ from unittest import mock ...@@ -3,15 +3,10 @@ from unittest import mock
class SampleObject: class SampleObject:
def __init__(self):
self.attr_sample1 = 1
self.attr_sample2 = 1
def method_sample1(self): def method_sample1(self): pass
pass
def method_sample2(self): def method_sample2(self): pass
pass
class TestSealable(unittest.TestCase): class TestSealable(unittest.TestCase):
......
...@@ -10,6 +10,8 @@ something = sentinel.Something ...@@ -10,6 +10,8 @@ something = sentinel.Something
something_else = sentinel.SomethingElse something_else = sentinel.SomethingElse
class SampleException(Exception): pass
class WithTest(unittest.TestCase): class WithTest(unittest.TestCase):
...@@ -20,14 +22,10 @@ class WithTest(unittest.TestCase): ...@@ -20,14 +22,10 @@ class WithTest(unittest.TestCase):
def test_with_statement_exception(self): def test_with_statement_exception(self):
try: with self.assertRaises(SampleException):
with patch('%s.something' % __name__, sentinel.Something2): with patch('%s.something' % __name__, sentinel.Something2):
self.assertEqual(something, sentinel.Something2, "unpatched") self.assertEqual(something, sentinel.Something2, "unpatched")
raise Exception('pow') raise SampleException()
except Exception:
pass
else:
self.fail("patch swallowed exception")
self.assertEqual(something, sentinel.Something) self.assertEqual(something, sentinel.Something)
...@@ -128,8 +126,7 @@ class WithTest(unittest.TestCase): ...@@ -128,8 +126,7 @@ class WithTest(unittest.TestCase):
def test_double_patch_instance_method(self): def test_double_patch_instance_method(self):
class C: class C:
def f(self): def f(self): pass
pass
c = C() c = C()
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment