|  | # 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/ | 
|  |  | 
|  | from tests.support import unittest2, inPy3k | 
|  |  | 
|  | try: | 
|  | unicode | 
|  | except NameError: | 
|  | # Python 3 | 
|  | unicode = str | 
|  | long = int | 
|  |  | 
|  | import inspect | 
|  | import sys | 
|  | from mock import Mock, MagicMock, _magics | 
|  |  | 
|  |  | 
|  |  | 
|  | class TestMockingMagicMethods(unittest2.TestCase): | 
|  |  | 
|  | def test_deleting_magic_methods(self): | 
|  | mock = Mock() | 
|  | self.assertFalse(hasattr(mock, '__getitem__')) | 
|  |  | 
|  | mock.__getitem__ = Mock() | 
|  | self.assertTrue(hasattr(mock, '__getitem__')) | 
|  |  | 
|  | del mock.__getitem__ | 
|  | self.assertFalse(hasattr(mock, '__getitem__')) | 
|  |  | 
|  |  | 
|  | def test_magicmock_del(self): | 
|  | mock = MagicMock() | 
|  | # before using getitem | 
|  | del mock.__getitem__ | 
|  | self.assertRaises(TypeError, lambda: mock['foo']) | 
|  |  | 
|  | mock = MagicMock() | 
|  | # this time use it first | 
|  | mock['foo'] | 
|  | del mock.__getitem__ | 
|  | self.assertRaises(TypeError, lambda: mock['foo']) | 
|  |  | 
|  |  | 
|  | def test_magic_method_wrapping(self): | 
|  | mock = Mock() | 
|  | def f(self, name): | 
|  | return self, 'fish' | 
|  |  | 
|  | mock.__getitem__ = f | 
|  | self.assertFalse(mock.__getitem__ is f) | 
|  | self.assertEqual(mock['foo'], (mock, 'fish')) | 
|  | self.assertEqual(mock.__getitem__('foo'), (mock, 'fish')) | 
|  |  | 
|  | mock.__getitem__ = mock | 
|  | self.assertTrue(mock.__getitem__ is mock) | 
|  |  | 
|  |  | 
|  | def test_magic_methods_isolated_between_mocks(self): | 
|  | mock1 = Mock() | 
|  | mock2 = Mock() | 
|  |  | 
|  | mock1.__iter__ = Mock(return_value=iter([])) | 
|  | self.assertEqual(list(mock1), []) | 
|  | self.assertRaises(TypeError, lambda: list(mock2)) | 
|  |  | 
|  |  | 
|  | def test_repr(self): | 
|  | mock = Mock() | 
|  | self.assertEqual(repr(mock), "<Mock id='%s'>" % id(mock)) | 
|  | mock.__repr__ = lambda s: 'foo' | 
|  | self.assertEqual(repr(mock), 'foo') | 
|  |  | 
|  |  | 
|  | def test_str(self): | 
|  | mock = Mock() | 
|  | self.assertEqual(str(mock), object.__str__(mock)) | 
|  | mock.__str__ = lambda s: 'foo' | 
|  | self.assertEqual(str(mock), 'foo') | 
|  |  | 
|  |  | 
|  | @unittest2.skipIf(inPy3k, "no unicode in Python 3") | 
|  | def test_unicode(self): | 
|  | mock = Mock() | 
|  | self.assertEqual(unicode(mock), unicode(str(mock))) | 
|  |  | 
|  | mock.__unicode__ = lambda s: unicode('foo') | 
|  | self.assertEqual(unicode(mock), unicode('foo')) | 
|  |  | 
|  |  | 
|  | def test_dict_methods(self): | 
|  | mock = Mock() | 
|  |  | 
|  | self.assertRaises(TypeError, lambda: mock['foo']) | 
|  | def _del(): | 
|  | del mock['foo'] | 
|  | def _set(): | 
|  | mock['foo'] = 3 | 
|  | self.assertRaises(TypeError, _del) | 
|  | self.assertRaises(TypeError, _set) | 
|  |  | 
|  | _dict = {} | 
|  | def getitem(s, name): | 
|  | return _dict[name] | 
|  | def setitem(s, name, value): | 
|  | _dict[name] = value | 
|  | def delitem(s, name): | 
|  | del _dict[name] | 
|  |  | 
|  | mock.__setitem__ = setitem | 
|  | mock.__getitem__ = getitem | 
|  | mock.__delitem__ = delitem | 
|  |  | 
|  | self.assertRaises(KeyError, lambda: mock['foo']) | 
|  | mock['foo'] = 'bar' | 
|  | self.assertEqual(_dict, {'foo': 'bar'}) | 
|  | self.assertEqual(mock['foo'], 'bar') | 
|  | del mock['foo'] | 
|  | self.assertEqual(_dict, {}) | 
|  |  | 
|  |  | 
|  | def test_numeric(self): | 
|  | original = mock = Mock() | 
|  | mock.value = 0 | 
|  |  | 
|  | self.assertRaises(TypeError, lambda: mock + 3) | 
|  |  | 
|  | def add(self, other): | 
|  | mock.value += other | 
|  | return self | 
|  | mock.__add__ = add | 
|  | self.assertEqual(mock + 3, mock) | 
|  | self.assertEqual(mock.value, 3) | 
|  |  | 
|  | del mock.__add__ | 
|  | def iadd(mock): | 
|  | mock += 3 | 
|  | self.assertRaises(TypeError, iadd, mock) | 
|  | mock.__iadd__ = add | 
|  | mock += 6 | 
|  | self.assertEqual(mock, original) | 
|  | self.assertEqual(mock.value, 9) | 
|  |  | 
|  | self.assertRaises(TypeError, lambda: 3 + mock) | 
|  | mock.__radd__ = add | 
|  | self.assertEqual(7 + mock, mock) | 
|  | self.assertEqual(mock.value, 16) | 
|  |  | 
|  |  | 
|  | @unittest2.skipIf(inPy3k, 'no truediv in Python 3') | 
|  | def test_truediv(self): | 
|  | mock = MagicMock() | 
|  | mock.__truediv__.return_value = 6 | 
|  |  | 
|  | context = {'mock': mock} | 
|  | code = 'from __future__ import division\nresult = mock / 7\n' | 
|  | exec(code, context) | 
|  | self.assertEqual(context['result'], 6) | 
|  |  | 
|  | mock.__rtruediv__.return_value = 3 | 
|  | code = 'from __future__ import division\nresult = 2 / mock\n' | 
|  | exec(code, context) | 
|  | self.assertEqual(context['result'], 3) | 
|  |  | 
|  |  | 
|  | @unittest2.skipIf(not inPy3k, 'truediv is available in Python 2') | 
|  | def test_no_truediv(self): | 
|  | self.assertRaises( | 
|  | AttributeError, getattr, MagicMock(), '__truediv__' | 
|  | ) | 
|  | self.assertRaises( | 
|  | AttributeError, getattr, MagicMock(), '__rtruediv__' | 
|  | ) | 
|  |  | 
|  |  | 
|  | def test_hash(self): | 
|  | mock = Mock() | 
|  | # test delegation | 
|  | self.assertEqual(hash(mock), Mock.__hash__(mock)) | 
|  |  | 
|  | def _hash(s): | 
|  | return 3 | 
|  | mock.__hash__ = _hash | 
|  | self.assertEqual(hash(mock), 3) | 
|  |  | 
|  |  | 
|  | def test_nonzero(self): | 
|  | m = Mock() | 
|  | self.assertTrue(bool(m)) | 
|  |  | 
|  | nonzero = lambda s: False | 
|  | if not inPy3k: | 
|  | m.__nonzero__ = nonzero | 
|  | else: | 
|  | m.__bool__ = nonzero | 
|  |  | 
|  | self.assertFalse(bool(m)) | 
|  |  | 
|  |  | 
|  | def test_comparison(self): | 
|  | # note: this test fails with Jython 2.5.1 due to a Jython bug | 
|  | #       it is fixed in jython 2.5.2 | 
|  | if not inPy3k: | 
|  | # incomparable in Python 3 | 
|  | self. assertEqual(Mock() < 3, object() < 3) | 
|  | self. assertEqual(Mock() > 3, object() > 3) | 
|  | self. assertEqual(Mock() <= 3, object() <= 3) | 
|  | self. assertEqual(Mock() >= 3, object() >= 3) | 
|  | else: | 
|  | self.assertRaises(TypeError, lambda: MagicMock() < object()) | 
|  | self.assertRaises(TypeError, lambda: object() < MagicMock()) | 
|  | self.assertRaises(TypeError, lambda: MagicMock() < MagicMock()) | 
|  | self.assertRaises(TypeError, lambda: MagicMock() > object()) | 
|  | self.assertRaises(TypeError, lambda: object() > MagicMock()) | 
|  | self.assertRaises(TypeError, lambda: MagicMock() > MagicMock()) | 
|  | self.assertRaises(TypeError, lambda: MagicMock() <= object()) | 
|  | self.assertRaises(TypeError, lambda: object() <= MagicMock()) | 
|  | self.assertRaises(TypeError, lambda: MagicMock() <= MagicMock()) | 
|  | self.assertRaises(TypeError, lambda: MagicMock() >= object()) | 
|  | self.assertRaises(TypeError, lambda: object() >= MagicMock()) | 
|  | self.assertRaises(TypeError, lambda: MagicMock() >= MagicMock()) | 
|  |  | 
|  | mock = Mock() | 
|  | def comp(s, o): | 
|  | return True | 
|  | mock.__lt__ = mock.__gt__ = mock.__le__ = mock.__ge__ = comp | 
|  | self. assertTrue(mock < 3) | 
|  | self. assertTrue(mock > 3) | 
|  | self. assertTrue(mock <= 3) | 
|  | self. assertTrue(mock >= 3) | 
|  |  | 
|  |  | 
|  | def test_equality(self): | 
|  | for mock in Mock(), MagicMock(): | 
|  | self.assertEqual(mock == mock, True) | 
|  | self.assertIsInstance(mock == mock, bool) | 
|  | self.assertEqual(mock != mock, False) | 
|  | self.assertIsInstance(mock != mock, bool) | 
|  | self.assertEqual(mock == object(), False) | 
|  | self.assertEqual(mock != object(), True) | 
|  |  | 
|  | def eq(self, other): | 
|  | return other == 3 | 
|  | mock.__eq__ = eq | 
|  | self.assertTrue(mock == 3) | 
|  | self.assertFalse(mock == 4) | 
|  |  | 
|  | def ne(self, other): | 
|  | return other == 3 | 
|  | mock.__ne__ = ne | 
|  | self.assertTrue(mock != 3) | 
|  | self.assertFalse(mock != 4) | 
|  |  | 
|  | mock = MagicMock() | 
|  | mock.__eq__.return_value = True | 
|  | self.assertIsInstance(mock == 3, bool) | 
|  | self.assertEqual(mock == 3, True) | 
|  |  | 
|  | mock.__ne__.return_value = False | 
|  | self.assertIsInstance(mock != 3, bool) | 
|  | self.assertEqual(mock != 3, False) | 
|  |  | 
|  |  | 
|  | def test_len_contains_iter(self): | 
|  | mock = Mock() | 
|  |  | 
|  | self.assertRaises(TypeError, len, mock) | 
|  | self.assertRaises(TypeError, iter, mock) | 
|  | self.assertRaises(TypeError, lambda: 'foo' in mock) | 
|  |  | 
|  | mock.__len__ = lambda s: 6 | 
|  | self.assertEqual(len(mock), 6) | 
|  |  | 
|  | mock.__contains__ = lambda s, o: o == 3 | 
|  | self.assertTrue(3 in mock) | 
|  | self.assertFalse(6 in mock) | 
|  |  | 
|  | mock.__iter__ = lambda s: iter('foobarbaz') | 
|  | self.assertEqual(list(mock), list('foobarbaz')) | 
|  |  | 
|  |  | 
|  | def test_magicmock(self): | 
|  | mock = MagicMock() | 
|  |  | 
|  | mock.__iter__.return_value = iter([1, 2, 3]) | 
|  | self.assertEqual(list(mock), [1, 2, 3]) | 
|  |  | 
|  | name = '__nonzero__' | 
|  | other = '__bool__' | 
|  | if inPy3k: | 
|  | name, other = other, name | 
|  | getattr(mock, name).return_value = False | 
|  | self.assertFalse(hasattr(mock, other)) | 
|  | self.assertFalse(bool(mock)) | 
|  |  | 
|  | for entry in _magics: | 
|  | self.assertTrue(hasattr(mock, entry)) | 
|  | self.assertFalse(hasattr(mock, '__imaginery__')) | 
|  |  | 
|  |  | 
|  | def test_magic_mock_equality(self): | 
|  | mock = MagicMock() | 
|  | self.assertIsInstance(mock == object(), bool) | 
|  | self.assertIsInstance(mock != object(), bool) | 
|  |  | 
|  | self.assertEqual(mock == object(), False) | 
|  | self.assertEqual(mock != object(), True) | 
|  | self.assertEqual(mock == mock, True) | 
|  | self.assertEqual(mock != mock, False) | 
|  |  | 
|  |  | 
|  | def test_magicmock_defaults(self): | 
|  | mock = MagicMock() | 
|  | self.assertEqual(int(mock), 1) | 
|  | self.assertEqual(complex(mock), 1j) | 
|  | self.assertEqual(float(mock), 1.0) | 
|  | self.assertEqual(long(mock), long(1)) | 
|  | self.assertNotIn(object(), mock) | 
|  | self.assertEqual(len(mock), 0) | 
|  | self.assertEqual(list(mock), []) | 
|  | self.assertEqual(hash(mock), object.__hash__(mock)) | 
|  | self.assertEqual(str(mock), object.__str__(mock)) | 
|  | self.assertEqual(unicode(mock), object.__str__(mock)) | 
|  | self.assertIsInstance(unicode(mock), unicode) | 
|  | self.assertTrue(bool(mock)) | 
|  | if not inPy3k: | 
|  | self.assertEqual(oct(mock), '1') | 
|  | else: | 
|  | # in Python 3 oct and hex use __index__ | 
|  | # so these tests are for __index__ in py3k | 
|  | self.assertEqual(oct(mock), '0o1') | 
|  | self.assertEqual(hex(mock), '0x1') | 
|  | # how to test __sizeof__ ? | 
|  |  | 
|  |  | 
|  | @unittest2.skipIf(inPy3k, "no __cmp__ in Python 3") | 
|  | def test_non_default_magic_methods(self): | 
|  | mock = MagicMock() | 
|  | self.assertRaises(AttributeError, lambda: mock.__cmp__) | 
|  |  | 
|  | mock = Mock() | 
|  | mock.__cmp__ = lambda s, o: 0 | 
|  |  | 
|  | self.assertEqual(mock, object()) | 
|  |  | 
|  |  | 
|  | def test_magic_methods_and_spec(self): | 
|  | class Iterable(object): | 
|  | def __iter__(self): | 
|  | pass | 
|  |  | 
|  | mock = Mock(spec=Iterable) | 
|  | self.assertRaises(AttributeError, lambda: mock.__iter__) | 
|  |  | 
|  | mock.__iter__ = Mock(return_value=iter([])) | 
|  | self.assertEqual(list(mock), []) | 
|  |  | 
|  | class NonIterable(object): | 
|  | pass | 
|  | mock = Mock(spec=NonIterable) | 
|  | self.assertRaises(AttributeError, lambda: mock.__iter__) | 
|  |  | 
|  | def set_int(): | 
|  | mock.__int__ = Mock(return_value=iter([])) | 
|  | self.assertRaises(AttributeError, set_int) | 
|  |  | 
|  | mock = MagicMock(spec=Iterable) | 
|  | self.assertEqual(list(mock), []) | 
|  | self.assertRaises(AttributeError, set_int) | 
|  |  | 
|  |  | 
|  | def test_magic_methods_and_spec_set(self): | 
|  | class Iterable(object): | 
|  | def __iter__(self): | 
|  | pass | 
|  |  | 
|  | mock = Mock(spec_set=Iterable) | 
|  | self.assertRaises(AttributeError, lambda: mock.__iter__) | 
|  |  | 
|  | mock.__iter__ = Mock(return_value=iter([])) | 
|  | self.assertEqual(list(mock), []) | 
|  |  | 
|  | class NonIterable(object): | 
|  | pass | 
|  | mock = Mock(spec_set=NonIterable) | 
|  | self.assertRaises(AttributeError, lambda: mock.__iter__) | 
|  |  | 
|  | def set_int(): | 
|  | mock.__int__ = Mock(return_value=iter([])) | 
|  | self.assertRaises(AttributeError, set_int) | 
|  |  | 
|  | mock = MagicMock(spec_set=Iterable) | 
|  | self.assertEqual(list(mock), []) | 
|  | self.assertRaises(AttributeError, set_int) | 
|  |  | 
|  |  | 
|  | def test_setting_unsupported_magic_method(self): | 
|  | mock = MagicMock() | 
|  | def set_setattr(): | 
|  | mock.__setattr__ = lambda self, name: None | 
|  | self.assertRaisesRegexp(AttributeError, | 
|  | "Attempting to set unsupported magic method '__setattr__'.", | 
|  | set_setattr | 
|  | ) | 
|  |  | 
|  |  | 
|  | def test_attributes_and_return_value(self): | 
|  | mock = MagicMock() | 
|  | attr = mock.foo | 
|  | def _get_type(obj): | 
|  | # the type of every mock (or magicmock) is a custom subclass | 
|  | # so the real type is the second in the mro | 
|  | return type(obj).__mro__[1] | 
|  | self.assertEqual(_get_type(attr), MagicMock) | 
|  |  | 
|  | returned = mock() | 
|  | self.assertEqual(_get_type(returned), MagicMock) | 
|  |  | 
|  |  | 
|  | def test_magic_methods_are_magic_mocks(self): | 
|  | mock = MagicMock() | 
|  | self.assertIsInstance(mock.__getitem__, MagicMock) | 
|  |  | 
|  | mock[1][2].__getitem__.return_value = 3 | 
|  | self.assertEqual(mock[1][2][3], 3) | 
|  |  | 
|  |  | 
|  | def test_magic_method_reset_mock(self): | 
|  | mock = MagicMock() | 
|  | str(mock) | 
|  | self.assertTrue(mock.__str__.called) | 
|  | mock.reset_mock() | 
|  | self.assertFalse(mock.__str__.called) | 
|  |  | 
|  |  | 
|  | @unittest2.skipUnless(sys.version_info[:2] >= (2, 6), | 
|  | "__dir__ not available until Python 2.6 or later") | 
|  | def test_dir(self): | 
|  | # overriding the default implementation | 
|  | for mock in Mock(), MagicMock(): | 
|  | def _dir(self): | 
|  | return ['foo'] | 
|  | mock.__dir__ = _dir | 
|  | self.assertEqual(dir(mock), ['foo']) | 
|  |  | 
|  |  | 
|  | @unittest2.skipIf('PyPy' in sys.version, "This fails differently on pypy") | 
|  | def test_bound_methods(self): | 
|  | m = Mock() | 
|  |  | 
|  | # XXXX should this be an expected failure instead? | 
|  |  | 
|  | # this seems like it should work, but is hard to do without introducing | 
|  | # other api inconsistencies. Failure message could be better though. | 
|  | m.__iter__ = [3].__iter__ | 
|  | self.assertRaises(TypeError, iter, m) | 
|  |  | 
|  |  | 
|  | def test_magic_method_type(self): | 
|  | class Foo(MagicMock): | 
|  | pass | 
|  |  | 
|  | foo = Foo() | 
|  | self.assertIsInstance(foo.__int__, Foo) | 
|  |  | 
|  |  | 
|  | def test_descriptor_from_class(self): | 
|  | m = MagicMock() | 
|  | type(m).__str__.return_value = 'foo' | 
|  | self.assertEqual(str(m), 'foo') | 
|  |  | 
|  |  | 
|  | def test_iterable_as_iter_return_value(self): | 
|  | m = MagicMock() | 
|  | m.__iter__.return_value = [1, 2, 3] | 
|  | self.assertEqual(list(m), [1, 2, 3]) | 
|  | self.assertEqual(list(m), [1, 2, 3]) | 
|  |  | 
|  | m.__iter__.return_value = iter([4, 5, 6]) | 
|  | self.assertEqual(list(m), [4, 5, 6]) | 
|  | self.assertEqual(list(m), []) | 
|  |  | 
|  |  | 
|  | if __name__ == '__main__': | 
|  | unittest2.main() |