123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509 |
- import math
- import unittest
- import os
- from asyncio import iscoroutinefunction
- from unittest.mock import AsyncMock, Mock, MagicMock, _magics
- class TestMockingMagicMethods(unittest.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.assertIsNot(mock.__getitem__, f)
- self.assertEqual(mock['foo'], (mock, 'fish'))
- self.assertEqual(mock.__getitem__('foo'), (mock, 'fish'))
- mock.__getitem__ = mock
- self.assertIs(mock.__getitem__, 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')
- 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)
- def test_division(self):
- original = mock = Mock()
- mock.value = 32
- self.assertRaises(TypeError, lambda: mock / 2)
- def truediv(self, other):
- mock.value /= other
- return self
- mock.__truediv__ = truediv
- self.assertEqual(mock / 2, mock)
- self.assertEqual(mock.value, 16)
- del mock.__truediv__
- def itruediv(mock):
- mock /= 4
- self.assertRaises(TypeError, itruediv, mock)
- mock.__itruediv__ = truediv
- mock /= 8
- self.assertEqual(mock, original)
- self.assertEqual(mock.value, 2)
- self.assertRaises(TypeError, lambda: 8 / mock)
- mock.__rtruediv__ = truediv
- self.assertEqual(0.5 / mock, mock)
- self.assertEqual(mock.value, 4)
- 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))
- m.__bool__ = lambda s: False
- self.assertFalse(bool(m))
- def test_comparison(self):
- 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)
- 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())
- 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.assertIn(3, mock)
- self.assertNotIn(6, 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])
- getattr(mock, '__bool__').return_value = False
- self.assertFalse(hasattr(mock, '__nonzero__'))
- self.assertFalse(bool(mock))
- for entry in _magics:
- self.assertTrue(hasattr(mock, entry))
- self.assertFalse(hasattr(mock, '__imaginary__'))
- 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_asyncmock_defaults(self):
- mock = AsyncMock()
- self.assertEqual(int(mock), 1)
- self.assertEqual(complex(mock), 1j)
- self.assertEqual(float(mock), 1.0)
- 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.assertTrue(bool(mock))
- self.assertEqual(round(mock), mock.__round__())
- self.assertEqual(math.trunc(mock), mock.__trunc__())
- self.assertEqual(math.floor(mock), mock.__floor__())
- self.assertEqual(math.ceil(mock), mock.__ceil__())
- self.assertTrue(iscoroutinefunction(mock.__aexit__))
- self.assertTrue(iscoroutinefunction(mock.__aenter__))
- self.assertIsInstance(mock.__aenter__, AsyncMock)
- self.assertIsInstance(mock.__aexit__, AsyncMock)
- # 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__ ?
- def test_magicmock_defaults(self):
- mock = MagicMock()
- self.assertEqual(int(mock), 1)
- self.assertEqual(complex(mock), 1j)
- self.assertEqual(float(mock), 1.0)
- 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.assertTrue(bool(mock))
- self.assertEqual(round(mock), mock.__round__())
- self.assertEqual(math.trunc(mock), mock.__trunc__())
- self.assertEqual(math.floor(mock), mock.__floor__())
- self.assertEqual(math.ceil(mock), mock.__ceil__())
- self.assertTrue(iscoroutinefunction(mock.__aexit__))
- self.assertTrue(iscoroutinefunction(mock.__aenter__))
- self.assertIsInstance(mock.__aenter__, AsyncMock)
- self.assertIsInstance(mock.__aexit__, AsyncMock)
- # 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__ ?
- def test_magic_methods_fspath(self):
- mock = MagicMock()
- expected_path = mock.__fspath__()
- mock.reset_mock()
- self.assertEqual(os.fspath(mock), expected_path)
- mock.__fspath__.assert_called_once()
- 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.assertRaisesRegex(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)
- 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'])
- 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), [])
- def test_matmul(self):
- m = MagicMock()
- self.assertIsInstance(m @ 1, MagicMock)
- m.__matmul__.return_value = 42
- m.__rmatmul__.return_value = 666
- m.__imatmul__.return_value = 24
- self.assertEqual(m @ 1, 42)
- self.assertEqual(1 @ m, 666)
- m @= 24
- self.assertEqual(m, 24)
- def test_divmod_and_rdivmod(self):
- m = MagicMock()
- self.assertIsInstance(divmod(5, m), MagicMock)
- m.__divmod__.return_value = (2, 1)
- self.assertEqual(divmod(m, 2), (2, 1))
- m = MagicMock()
- foo = divmod(2, m)
- self.assertIsInstance(foo, MagicMock)
- foo_direct = m.__divmod__(2)
- self.assertIsInstance(foo_direct, MagicMock)
- bar = divmod(m, 2)
- self.assertIsInstance(bar, MagicMock)
- bar_direct = m.__rdivmod__(2)
- self.assertIsInstance(bar_direct, MagicMock)
- # http://bugs.python.org/issue23310
- # Check if you can change behaviour of magic methods in MagicMock init
- def test_magic_in_initialization(self):
- m = MagicMock(**{'__str__.return_value': "12"})
- self.assertEqual(str(m), "12")
- def test_changing_magic_set_in_initialization(self):
- m = MagicMock(**{'__str__.return_value': "12"})
- m.__str__.return_value = "13"
- self.assertEqual(str(m), "13")
- m = MagicMock(**{'__str__.return_value': "12"})
- m.configure_mock(**{'__str__.return_value': "14"})
- self.assertEqual(str(m), "14")
- if __name__ == '__main__':
- unittest.main()
|