summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChris Withers <chris@withers.org>2019-05-01 22:04:04 (GMT)
committerGitHub <noreply@github.com>2019-05-01 22:04:04 (GMT)
commitadbf178e49113b2de0042e86a1228560475a65c5 (patch)
tree871ac21aec993e310f915cf2781909282a7a03e9
parentb7378d77289c911ca6a0c0afaf513879002df7d5 (diff)
downloadcpython-adbf178e49113b2de0042e86a1228560475a65c5.zip
cpython-adbf178e49113b2de0042e86a1228560475a65c5.tar.gz
cpython-adbf178e49113b2de0042e86a1228560475a65c5.tar.bz2
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.
-rw-r--r--Lib/unittest/mock.py61
-rw-r--r--Lib/unittest/test/testmock/support.py3
-rw-r--r--Lib/unittest/test/testmock/testcallable.py3
-rw-r--r--Lib/unittest/test/testmock/testhelpers.py195
-rw-r--r--Lib/unittest/test/testmock/testmagicmethods.py6
-rw-r--r--Lib/unittest/test/testmock/testmock.py126
-rw-r--r--Lib/unittest/test/testmock/testpatch.py164
-rw-r--r--Lib/unittest/test/testmock/testsealable.py9
-rw-r--r--Lib/unittest/test/testmock/testwith.py13
9 files changed, 263 insertions, 317 deletions
diff --git a/Lib/unittest/mock.py b/Lib/unittest/mock.py
index 721e91f..351aba5 100644
--- a/Lib/unittest/mock.py
+++ b/Lib/unittest/mock.py
@@ -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,
diff --git a/Lib/unittest/test/testmock/support.py b/Lib/unittest/test/testmock/support.py
index f146be2..49986d6 100644
--- a/Lib/unittest/test/testmock/support.py
+++ b/Lib/unittest/test/testmock/support.py
@@ -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):
diff --git a/Lib/unittest/test/testmock/testcallable.py b/Lib/unittest/test/testmock/testcallable.py
index 34474c4..5eadc00 100644
--- a/Lib/unittest/test/testmock/testcallable.py
+++ b/Lib/unittest/test/testmock/testcallable.py
@@ -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
diff --git a/Lib/unittest/test/testmock/testhelpers.py b/Lib/unittest/test/testmock/testhelpers.py
index e321976..301bca4 100644
--- a/Lib/unittest/test/testmock/testhelpers.py
+++ b/Lib/unittest/test/testmock/testhelpers.py
@@ -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):
diff --git a/Lib/unittest/test/testmock/testmagicmethods.py b/Lib/unittest/test/testmock/testmagicmethods.py
index 69dfe60..130a339 100644
--- a/Lib/unittest/test/testmock/testmagicmethods.py
+++ b/Lib/unittest/test/testmock/testmagicmethods.py
@@ -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__)
diff --git a/Lib/unittest/test/testmock/testmock.py b/Lib/unittest/test/testmock/testmock.py
index 9bef51a..5f917dd 100644
--- a/Lib/unittest/test/testmock/testmock.py
+++ b/Lib/unittest/test/testmock/testmock.py
@@ -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
diff --git a/Lib/unittest/test/testmock/testpatch.py b/Lib/unittest/test/testmock/testpatch.py
index e5abd9b..3295c5b 100644
--- a/Lib/unittest/test/testmock/testpatch.py
+++ b/Lib/unittest/test/testmock/testpatch.py
@@ -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()
diff --git a/Lib/unittest/test/testmock/testsealable.py b/Lib/unittest/test/testmock/testsealable.py
index 0e72b32..59f5233 100644
--- a/Lib/unittest/test/testmock/testsealable.py
+++ b/Lib/unittest/test/testmock/testsealable.py
@@ -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):
diff --git a/Lib/unittest/test/testmock/testwith.py b/Lib/unittest/test/testmock/testwith.py
index ec4e540..37100b8 100644
--- a/Lib/unittest/test/testmock/testwith.py
+++ b/Lib/unittest/test/testmock/testwith.py
@@ -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()