diff options
Diffstat (limited to 'mock/tests/testmock.py')
-rw-r--r-- | mock/tests/testmock.py | 414 |
1 files changed, 116 insertions, 298 deletions
diff --git a/mock/tests/testmock.py b/mock/tests/testmock.py index 8bb8759..5f6045a 100644 --- a/mock/tests/testmock.py +++ b/mock/tests/testmock.py @@ -1,18 +1,30 @@ +# Copyright (C) 2007-2012 Michael Foord & the mock team +# E-mail: fuzzyman AT voidspace DOT org DOT uk +# http://www.voidspace.org.uk/python/mock/ + import copy +import pickle import re import sys import tempfile +import six import unittest -from mock.tests.support import ALWAYS_EQ -from mock.tests.support import is_instance -from mock import ( + +import mock +from mock.mock import ( call, DEFAULT, patch, sentinel, MagicMock, Mock, NonCallableMock, - NonCallableMagicMock, AsyncMock, - create_autospec, mock + NonCallableMagicMock, _Call, _CallList, + create_autospec ) -from mock.mock import _Call, _CallList +from mock.tests.support import is_instance + + +try: + unicode +except NameError: + unicode = str class Iter(object): @@ -38,7 +50,14 @@ class Something(object): def smeth(a, b, c, d=None): pass -def something(a): pass +class Subclass(MagicMock): + pass + + +class Thing(object): + attribute = 6 + foo = 'bar' + class MockTest(unittest.TestCase): @@ -47,7 +66,7 @@ class MockTest(unittest.TestCase): # if __all__ is badly defined then import * will raise an error # We have to exec it because you can't import * inside a method # in Python 3 - exec("from unittest.mock import *") + exec("from mock import *") def test_constructor(self): @@ -196,8 +215,7 @@ class MockTest(unittest.TestCase): mock = create_autospec(f) mock.side_effect = ValueError('Bazinga!') - self.assertRaisesRegex(ValueError, 'Bazinga!', mock) - + self.assertRaisesRegexp(ValueError, 'Bazinga!', mock) def test_reset_mock(self): parent = Mock() @@ -263,7 +281,7 @@ class MockTest(unittest.TestCase): ret_val = mock(sentinel.Arg) self.assertTrue(mock.called, "called not set") - self.assertEqual(mock.call_count, 1, "call_count incorrect") + self.assertEqual(mock.call_count, 1, "call_count incoreect") self.assertEqual(mock.call_args, ((sentinel.Arg,), {}), "call_args not set") self.assertEqual(mock.call_args.args, (sentinel.Arg,), @@ -323,8 +341,6 @@ class MockTest(unittest.TestCase): self.assertFalse(mm != mock.ANY) self.assertTrue(mock.ANY == mm) self.assertFalse(mock.ANY != mm) - self.assertTrue(mm == ALWAYS_EQ) - self.assertFalse(mm != ALWAYS_EQ) call1 = mock.call(mock.MagicMock()) call2 = mock.call(mock.ANY) @@ -333,11 +349,6 @@ class MockTest(unittest.TestCase): self.assertTrue(call2 == call1) self.assertFalse(call2 != call1) - self.assertTrue(call1 == ALWAYS_EQ) - self.assertFalse(call1 != ALWAYS_EQ) - self.assertFalse(call1 == 1) - self.assertTrue(call1 != 1) - def test_assert_called_with(self): mock = Mock() @@ -373,7 +384,8 @@ class MockTest(unittest.TestCase): # Expected call doesn't match the spec's signature with self.assertRaises(AssertionError) as cm: mock.assert_called_with(e=8) - self.assertIsInstance(cm.exception.__cause__, TypeError) + if hasattr(cm.exception, '__cause__'): + self.assertIsInstance(cm.exception.__cause__, TypeError) def test_assert_called_with_method_spec(self): @@ -396,14 +408,6 @@ class MockTest(unittest.TestCase): _check(mock) - def test_assert_called_exception_message(self): - msg = "Expected '{0}' to have been called" - with self.assertRaisesRegex(AssertionError, msg.format('mock')): - Mock().assert_called() - with self.assertRaisesRegex(AssertionError, msg.format('test_name')): - Mock(name="test_name").assert_called() - - def test_assert_called_once_with(self): mock = Mock() mock() @@ -431,7 +435,7 @@ class MockTest(unittest.TestCase): m = Mock() m(1) m(2) - self.assertRaisesRegex(AssertionError, + self.assertRaisesRegexp(AssertionError, re.escape("Calls: [call(1), call(2)]"), lambda: m.assert_called_once_with(2)) @@ -449,7 +453,8 @@ class MockTest(unittest.TestCase): # Expected call doesn't match the spec's signature with self.assertRaises(AssertionError) as cm: mock.assert_called_once_with(e=8) - self.assertIsInstance(cm.exception.__cause__, TypeError) + if hasattr(cm.exception, '__cause__'): + self.assertIsInstance(cm.exception.__cause__, TypeError) # Mock called more than once => always fails mock(4, 5, 6) self.assertRaises(AssertionError, mock.assert_called_once_with, @@ -530,7 +535,7 @@ class MockTest(unittest.TestCase): # this should be allowed mock.something - self.assertRaisesRegex( + self.assertRaisesRegexp( AttributeError, "Mock object has no attribute 'something_else'", getattr, mock, 'something_else' @@ -548,12 +553,12 @@ class MockTest(unittest.TestCase): mock.x mock.y mock.__something__ - self.assertRaisesRegex( + self.assertRaisesRegexp( AttributeError, "Mock object has no attribute 'z'", getattr, mock, 'z' ) - self.assertRaisesRegex( + self.assertRaisesRegexp( AttributeError, "Mock object has no attribute '__foobar__'", getattr, mock, '__foobar__' @@ -715,53 +720,6 @@ class MockTest(unittest.TestCase): self.assertRaises(StopIteration, mock.method) - def test_magic_method_wraps_dict(self): - data = {'foo': 'bar'} - - wrapped_dict = MagicMock(wraps=data) - self.assertEqual(wrapped_dict.get('foo'), 'bar') - self.assertEqual(wrapped_dict['foo'], 'bar') - self.assertTrue('foo' in wrapped_dict) - - # return_value is non-sentinel and takes precedence over wrapped value. - wrapped_dict.get.return_value = 'return_value' - self.assertEqual(wrapped_dict.get('foo'), 'return_value') - - # return_value is sentinel and hence wrapped value is returned. - wrapped_dict.get.return_value = sentinel.DEFAULT - self.assertEqual(wrapped_dict.get('foo'), 'bar') - - self.assertEqual(wrapped_dict.get('baz'), None) - with self.assertRaises(KeyError): - wrapped_dict['baz'] - self.assertFalse('bar' in wrapped_dict) - - data['baz'] = 'spam' - self.assertEqual(wrapped_dict.get('baz'), 'spam') - self.assertEqual(wrapped_dict['baz'], 'spam') - self.assertTrue('baz' in wrapped_dict) - - del data['baz'] - self.assertEqual(wrapped_dict.get('baz'), None) - - - def test_magic_method_wraps_class(self): - - class Foo: - - def __getitem__(self, index): - return index - - def __custom_method__(self): - return "foo" - - - klass = MagicMock(wraps=Foo) - obj = klass() - self.assertEqual(obj.__getitem__(2), 2) - self.assertEqual(obj.__custom_method__(), "foo") - - def test_exceptional_side_effect(self): mock = Mock(side_effect=AttributeError) self.assertRaises(AttributeError, mock) @@ -780,13 +738,13 @@ class MockTest(unittest.TestCase): def test_assert_called_with_message(self): mock = Mock() - self.assertRaisesRegex(AssertionError, 'not called', + self.assertRaisesRegexp(AssertionError, 'not called', mock.assert_called_with) def test_assert_called_once_with_message(self): mock = Mock(name='geoffrey') - self.assertRaisesRegex(AssertionError, + self.assertRaisesRegexp(AssertionError, r"Expected 'geoffrey' to be called once\.", mock.assert_called_once_with) @@ -836,8 +794,10 @@ class MockTest(unittest.TestCase): mock = Mock(spec=X) self.assertIsInstance(mock, X) - mock = Mock(spec=X()) - self.assertIsInstance(mock, X) + if not six.PY2: + # This isn't true on Py2, we should fix if anyone complains: + mock = Mock(spec=X()) + self.assertIsInstance(mock, X) self.assertIs(mock.__class__, X) self.assertEqual(Mock().__class__.__name__, 'Mock') @@ -845,8 +805,10 @@ class MockTest(unittest.TestCase): mock = Mock(spec_set=X) self.assertIsInstance(mock, X) - mock = Mock(spec_set=X()) - self.assertIsInstance(mock, X) + if not six.PY2: + # This isn't true on Py2, we should fix if anyone complains: + mock = Mock(spec_set=X()) + self.assertIsInstance(mock, X) def test_setting_attribute_with_spec_set(self): @@ -874,6 +836,42 @@ class MockTest(unittest.TestCase): copy.copy(Mock()) + @unittest.skipIf(six.PY3, "no old style classes in Python 3") + def test_spec_old_style_classes(self): + class Foo: + bar = 7 + + mock = Mock(spec=Foo) + mock.bar = 6 + self.assertRaises(AttributeError, lambda: mock.foo) + + mock = Mock(spec=Foo()) + mock.bar = 6 + self.assertRaises(AttributeError, lambda: mock.foo) + + + @unittest.skipIf(six.PY3, "no old style classes in Python 3") + def test_spec_set_old_style_classes(self): + class Foo: + bar = 7 + + mock = Mock(spec_set=Foo) + mock.bar = 6 + self.assertRaises(AttributeError, lambda: mock.foo) + + def _set(): + mock.foo = 3 + self.assertRaises(AttributeError, _set) + + mock = Mock(spec_set=Foo()) + mock.bar = 6 + self.assertRaises(AttributeError, lambda: mock.foo) + + def _set(): + mock.foo = 3 + self.assertRaises(AttributeError, _set) + + def test_subclass_with_properties(self): class SubClass(Mock): def _get(self): @@ -897,7 +895,6 @@ class MockTest(unittest.TestCase): def test_setting_call(self): mock = Mock() def __call__(self, a): - self._increment_mock_call(a) return self._mock_call(a) type(mock).__call__ = __call__ @@ -910,7 +907,7 @@ class MockTest(unittest.TestCase): def test_dir(self): mock = Mock() attrs = set(dir(mock)) - type_attrs = set([m for m in dir(Mock) if not m.startswith('_')]) + type_attrs = {m for m in dir(Mock) if not m.startswith('_')} # all public attributes from the type are included self.assertEqual(set(), type_attrs - attrs) @@ -1183,7 +1180,7 @@ class MockTest(unittest.TestCase): m = Mock() m.foo = m repr(m.foo()) - self.assertRegex(repr(m.foo()), r"<Mock name='mock\(\)' id='\d+'>") + self.assertRegexpMatches(repr(m.foo()), r"<Mock name='mock\(\)' id='\d+'>") def test_mock_calls_contains(self): @@ -1283,16 +1280,6 @@ class MockTest(unittest.TestCase): self.assertRaises(StopIteration, mock) - def test_side_effect_iterator_exceptions(self): - for Klass in Mock, MagicMock: - iterable = (ValueError, 3, KeyError, 6) - m = Klass(side_effect=iterable) - self.assertRaises(ValueError, m) - self.assertEqual(m(), 3) - self.assertRaises(KeyError, m) - self.assertEqual(m(), 6) - - def test_side_effect_setting_iterator(self): mock = Mock() mock.side_effect = iter([1, 2, 3]) @@ -1314,6 +1301,17 @@ class MockTest(unittest.TestCase): self.assertRaises(StopIteration, mock) self.assertIs(mock.side_effect, this_iter) + + def test_side_effect_iterator_exceptions(self): + for Klass in Mock, MagicMock: + iterable = (ValueError, 3, KeyError, 6) + m = Klass(side_effect=iterable) + self.assertRaises(ValueError, m) + self.assertEqual(m(), 3) + self.assertRaises(KeyError, m) + self.assertEqual(m(), 6) + + def test_side_effect_iterator_default(self): mock = Mock(return_value=2) mock.side_effect = iter([1, DEFAULT]) @@ -1403,54 +1401,6 @@ class MockTest(unittest.TestCase): ) - def test_assert_has_calls_nested_spec(self): - class Something: - - def __init__(self): pass - def meth(self, a, b, c, d=None): pass - - class Foo: - - def __init__(self, a): pass - def meth1(self, a, b): pass - - mock_class = create_autospec(Something) - - for m in [mock_class, mock_class()]: - m.meth(1, 2, 3, d=1) - m.assert_has_calls([call.meth(1, 2, 3, d=1)]) - m.assert_has_calls([call.meth(1, 2, 3, 1)]) - - mock_class.reset_mock() - - for m in [mock_class, mock_class()]: - self.assertRaises(AssertionError, m.assert_has_calls, [call.Foo()]) - m.Foo(1).meth1(1, 2) - m.assert_has_calls([call.Foo(1), call.Foo(1).meth1(1, 2)]) - m.Foo.assert_has_calls([call(1), call().meth1(1, 2)]) - - mock_class.reset_mock() - - invalid_calls = [call.meth(1), - call.non_existent(1), - call.Foo().non_existent(1), - call.Foo().meth(1, 2, 3, 4)] - - for kall in invalid_calls: - self.assertRaises(AssertionError, - mock_class.assert_has_calls, - [kall] - ) - - - def test_assert_has_calls_nested_without_spec(self): - m = MagicMock() - m().foo().bar().baz() - m.one().two().three() - calls = call.one().two().three().call_list() - m.assert_has_calls(calls) - - def test_assert_has_calls_with_function_spec(self): def f(a, b, c, d=None): pass @@ -1482,34 +1432,6 @@ class MockTest(unittest.TestCase): mock.assert_has_calls(calls[:-1]) mock.assert_has_calls(calls[:-1], any_order=True) - def test_assert_has_calls_not_matching_spec_error(self): - def f(x=None): pass - - mock = Mock(spec=f) - mock(1) - - with self.assertRaisesRegex( - AssertionError, - '^{}$'.format( - re.escape('Calls not found.\n' - 'Expected: [call()]\n' - 'Actual: [call(1)]'))) as cm: - mock.assert_has_calls([call()]) - self.assertIsNone(cm.exception.__cause__) - - - with self.assertRaisesRegex( - AssertionError, - '^{}$'.format( - re.escape( - 'Error processing expected calls.\n' - "Errors: [None, TypeError('too many positional arguments')]\n" - "Expected: [call(), call(1, 2)]\n" - 'Actual: [call(1)]').replace( - "arguments\\'", "arguments\\',?" - ))) as cm: - mock.assert_has_calls([call(), call(1, 2)]) - self.assertIsInstance(cm.exception.__cause__, TypeError) def test_assert_any_call(self): mock = Mock() @@ -1553,7 +1475,8 @@ class MockTest(unittest.TestCase): # Expected call doesn't match the spec's signature with self.assertRaises(AssertionError) as cm: mock.assert_any_call(e=8) - self.assertIsInstance(cm.exception.__cause__, TypeError) + if hasattr(cm.exception, '__cause__'): + self.assertIsInstance(cm.exception.__cause__, TypeError) def test_mock_calls_create_autospec(self): @@ -1587,7 +1510,6 @@ class MockTest(unittest.TestCase): @staticmethod def static_method(): pass for method in ('class_method', 'static_method'): - with self.subTest(method=method): mock_method = mock.create_autospec(getattr(TestClass, method)) mock_method() mock_method.assert_called_once_with() @@ -1596,10 +1518,9 @@ class MockTest(unittest.TestCase): #Issue21238 def test_mock_unsafe(self): m = Mock() - msg = "Attributes cannot start with 'assert' or 'assret'" - with self.assertRaisesRegex(AttributeError, msg): + with self.assertRaises(AttributeError): m.assert_foo_call() - with self.assertRaisesRegex(AttributeError, msg): + with self.assertRaises(AttributeError): m.assret_foo_call() m = Mock(unsafe=True) m.assert_foo_call() @@ -1616,7 +1537,7 @@ class MockTest(unittest.TestCase): def test_assert_not_called_message(self): m = Mock() m(1, 2) - self.assertRaisesRegex(AssertionError, + self.assertRaisesRegexp(AssertionError, re.escape("Calls: [call(1, 2)]"), m.assert_not_called) @@ -1645,7 +1566,7 @@ class MockTest(unittest.TestCase): m = Mock() m(1, 2) m(3) - self.assertRaisesRegex(AssertionError, + self.assertRaisesRegexp(AssertionError, re.escape("Calls: [call(1, 2), call(3)]"), m.assert_called_once) @@ -1655,11 +1576,11 @@ class MockTest(unittest.TestCase): m.assert_called_once() self.assertNotIn("Calls:", str(e.exception)) - #Issue37212 printout of keyword args now preserves the original order - def test_ordered_call_signature(self): + #Issue21256 printout of keyword args should be in deterministic order + def test_sorted_call_signature(self): m = Mock() m.hello(name='hello', daddy='hero') - text = "call(name='hello', daddy='hero')" + text = "call(daddy='hero', name='hello')" self.assertEqual(repr(m.hello.call_args), text) #Issue21270 overrides tuple methods for mock.call objects @@ -1685,23 +1606,11 @@ class MockTest(unittest.TestCase): self.assertNotEqual(m.side_effect, None) def test_reset_sideeffect(self): - m = Mock(return_value=10, side_effect=[2, 3]) + m = Mock(return_value=10, side_effect=[2,3]) m.reset_mock(side_effect=True) self.assertEqual(m.return_value, 10) self.assertEqual(m.side_effect, None) - def test_reset_return_with_children(self): - m = MagicMock(f=MagicMock(return_value=1)) - self.assertEqual(m.f(), 1) - m.reset_mock(return_value=True) - self.assertNotEqual(m.f(), 1) - - def test_reset_return_with_children_side_effect(self): - m = MagicMock(f=MagicMock(side_effect=[2, 3])) - self.assertNotEqual(m.f.side_effect, None) - m.reset_mock(side_effect=True) - self.assertEqual(m.f.side_effect, None) - def test_mock_add_spec(self): class _One(object): one = 1 @@ -1773,8 +1682,7 @@ class MockTest(unittest.TestCase): def test_adding_child_mock(self): - for Klass in (NonCallableMock, Mock, MagicMock, NonCallableMagicMock, - AsyncMock): + for Klass in NonCallableMock, Mock, MagicMock, NonCallableMagicMock: mock = Klass() mock.foo = Mock() @@ -1857,24 +1765,6 @@ class MockTest(unittest.TestCase): self.assertEqual(lines[1], 'Norwegian Blue') self.assertEqual(list(f1), []) - def test_mock_open_using_next(self): - mocked_open = mock.mock_open(read_data='1st line\n2nd line\n3rd line') - f1 = mocked_open('a-name') - line1 = next(f1) - line2 = f1.__next__() - lines = [line for line in f1] - self.assertEqual(line1, '1st line\n') - self.assertEqual(line2, '2nd line\n') - self.assertEqual(lines[0], '3rd line') - self.assertEqual(list(f1), []) - with self.assertRaises(StopIteration): - next(f1) - - def test_mock_open_next_with_readline_with_return_value(self): - mopen = mock.mock_open(read_data='foo\nbarn') - mopen.return_value.readline.return_value = 'abc' - self.assertEqual('abc', next(mopen())) - def test_mock_open_write(self): # Test exception in file writing write() mock_namedtemp = mock.mock_open(mock.MagicMock(name='JLV')) @@ -1894,6 +1784,7 @@ class MockTest(unittest.TestCase): self.assertEqual('abc', first) self.assertEqual('abc', second) + def test_mock_open_after_eof(self): # read, readline and readlines should work after end of file. _open = mock.mock_open(read_data='foo') @@ -1906,6 +1797,7 @@ class MockTest(unittest.TestCase): self.assertEqual([], h.readlines()) self.assertEqual([], h.readlines()) + def test_mock_parents(self): for Klass in Mock, MagicMock: m = Klass() @@ -1968,55 +1860,6 @@ class MockTest(unittest.TestCase): self.assertEqual(m.mock_calls, call().foo().call_list()) - def test_attach_mock_patch_autospec(self): - parent = Mock() - - with mock.patch(f'{__name__}.something', autospec=True) as mock_func: - self.assertEqual(mock_func.mock._extract_mock_name(), 'something') - parent.attach_mock(mock_func, 'child') - parent.child(1) - something(2) - mock_func(3) - - parent_calls = [call.child(1), call.child(2), call.child(3)] - child_calls = [call(1), call(2), call(3)] - self.assertEqual(parent.mock_calls, parent_calls) - self.assertEqual(parent.child.mock_calls, child_calls) - self.assertEqual(something.mock_calls, child_calls) - self.assertEqual(mock_func.mock_calls, child_calls) - self.assertIn('mock.child', repr(parent.child.mock)) - self.assertEqual(mock_func.mock._extract_mock_name(), 'mock.child') - - - def test_attach_mock_patch_autospec_signature(self): - with mock.patch(f'{__name__}.Something.meth', autospec=True) as mocked: - manager = Mock() - manager.attach_mock(mocked, 'attach_meth') - obj = Something() - obj.meth(1, 2, 3, d=4) - manager.assert_has_calls([call.attach_meth(mock.ANY, 1, 2, 3, d=4)]) - obj.meth.assert_has_calls([call(mock.ANY, 1, 2, 3, d=4)]) - mocked.assert_has_calls([call(mock.ANY, 1, 2, 3, d=4)]) - - with mock.patch(f'{__name__}.something', autospec=True) as mocked: - manager = Mock() - manager.attach_mock(mocked, 'attach_func') - something(1) - manager.assert_has_calls([call.attach_func(1)]) - something.assert_has_calls([call(1)]) - mocked.assert_has_calls([call(1)]) - - with mock.patch(f'{__name__}.Something', autospec=True) as mocked: - manager = Mock() - manager.attach_mock(mocked, 'attach_obj') - obj = Something() - obj.meth(1, 2, 3, d=4) - manager.assert_has_calls([call.attach_obj(), - call.attach_obj().meth(1, 2, 3, d=4)]) - obj.meth.assert_has_calls([call(1, 2, 3, d=4)]) - mocked.assert_has_calls([call(), call().meth(1, 2, 3, d=4)]) - - def test_attribute_deletion(self): for mock in (Mock(), MagicMock(), NonCallableMagicMock(), NonCallableMock()): @@ -2089,31 +1932,14 @@ class MockTest(unittest.TestCase): self.assertEqual(type(call.parent), _Call) self.assertEqual(type(call.parent().parent), _Call) - def test_parent_propagation_with_create_autospec(self): - def foo(a, b): pass mock = Mock() mock.child = create_autospec(foo) mock.child(1, 2) - self.assertRaises(TypeError, mock.child, 1) self.assertEqual(mock.mock_calls, [call.child(1, 2)]) - self.assertIn('mock.child', repr(mock.child.mock)) - - def test_parent_propagation_with_autospec_attach_mock(self): - - def foo(a, b): pass - - parent = Mock() - parent.attach_mock(create_autospec(foo, name='bar'), 'child') - parent.child(1, 2) - - self.assertRaises(TypeError, parent.child, 1) - self.assertEqual(parent.child.mock_calls, [call.child(1, 2)]) - self.assertIn('mock.child', repr(parent.child.mock)) - def test_isinstance_under_settrace(self): # bpo-36593 : __class__ is not set for a class that has __class__ @@ -2123,35 +1949,27 @@ class MockTest(unittest.TestCase): # dependent on unittest.mock.patch. In testpatch.PatchTest # test_patch_dict_test_prefix and test_patch_test_prefix not restoring # causes the objects patched to go out of sync - - old_patch = unittest.mock.patch - + old_patch = mock.patch # Directly using __setattr__ on unittest.mock causes current imported # reference to be updated. Use a lambda so that during cleanup the # re-imported new reference is updated. - self.addCleanup(lambda patch: setattr(unittest.mock, 'patch', patch), + self.addCleanup(lambda patch: setattr(mock, 'patch', patch), old_patch) - with patch.dict('sys.modules'): - del sys.modules['unittest.mock'] - + del sys.modules['mock.mock'] # 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) - - from unittest.mock import ( + from mock.mock import ( Mock, MagicMock, NonCallableMock, NonCallableMagicMock ) - mocks = [ - Mock, MagicMock, NonCallableMock, NonCallableMagicMock, AsyncMock + Mock, MagicMock, NonCallableMock, NonCallableMagicMock ] - - for mock in mocks: - obj = mock(spec=Something) + for mock_ in mocks: + obj = mock_(spec=Something) self.assertIsInstance(obj, Something) |