testmagicmethods.py 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509
  1. import math
  2. import unittest
  3. import os
  4. from asyncio import iscoroutinefunction
  5. from unittest.mock import AsyncMock, Mock, MagicMock, _magics
  6. class TestMockingMagicMethods(unittest.TestCase):
  7. def test_deleting_magic_methods(self):
  8. mock = Mock()
  9. self.assertFalse(hasattr(mock, '__getitem__'))
  10. mock.__getitem__ = Mock()
  11. self.assertTrue(hasattr(mock, '__getitem__'))
  12. del mock.__getitem__
  13. self.assertFalse(hasattr(mock, '__getitem__'))
  14. def test_magicmock_del(self):
  15. mock = MagicMock()
  16. # before using getitem
  17. del mock.__getitem__
  18. self.assertRaises(TypeError, lambda: mock['foo'])
  19. mock = MagicMock()
  20. # this time use it first
  21. mock['foo']
  22. del mock.__getitem__
  23. self.assertRaises(TypeError, lambda: mock['foo'])
  24. def test_magic_method_wrapping(self):
  25. mock = Mock()
  26. def f(self, name):
  27. return self, 'fish'
  28. mock.__getitem__ = f
  29. self.assertIsNot(mock.__getitem__, f)
  30. self.assertEqual(mock['foo'], (mock, 'fish'))
  31. self.assertEqual(mock.__getitem__('foo'), (mock, 'fish'))
  32. mock.__getitem__ = mock
  33. self.assertIs(mock.__getitem__, mock)
  34. def test_magic_methods_isolated_between_mocks(self):
  35. mock1 = Mock()
  36. mock2 = Mock()
  37. mock1.__iter__ = Mock(return_value=iter([]))
  38. self.assertEqual(list(mock1), [])
  39. self.assertRaises(TypeError, lambda: list(mock2))
  40. def test_repr(self):
  41. mock = Mock()
  42. self.assertEqual(repr(mock), "<Mock id='%s'>" % id(mock))
  43. mock.__repr__ = lambda s: 'foo'
  44. self.assertEqual(repr(mock), 'foo')
  45. def test_str(self):
  46. mock = Mock()
  47. self.assertEqual(str(mock), object.__str__(mock))
  48. mock.__str__ = lambda s: 'foo'
  49. self.assertEqual(str(mock), 'foo')
  50. def test_dict_methods(self):
  51. mock = Mock()
  52. self.assertRaises(TypeError, lambda: mock['foo'])
  53. def _del():
  54. del mock['foo']
  55. def _set():
  56. mock['foo'] = 3
  57. self.assertRaises(TypeError, _del)
  58. self.assertRaises(TypeError, _set)
  59. _dict = {}
  60. def getitem(s, name):
  61. return _dict[name]
  62. def setitem(s, name, value):
  63. _dict[name] = value
  64. def delitem(s, name):
  65. del _dict[name]
  66. mock.__setitem__ = setitem
  67. mock.__getitem__ = getitem
  68. mock.__delitem__ = delitem
  69. self.assertRaises(KeyError, lambda: mock['foo'])
  70. mock['foo'] = 'bar'
  71. self.assertEqual(_dict, {'foo': 'bar'})
  72. self.assertEqual(mock['foo'], 'bar')
  73. del mock['foo']
  74. self.assertEqual(_dict, {})
  75. def test_numeric(self):
  76. original = mock = Mock()
  77. mock.value = 0
  78. self.assertRaises(TypeError, lambda: mock + 3)
  79. def add(self, other):
  80. mock.value += other
  81. return self
  82. mock.__add__ = add
  83. self.assertEqual(mock + 3, mock)
  84. self.assertEqual(mock.value, 3)
  85. del mock.__add__
  86. def iadd(mock):
  87. mock += 3
  88. self.assertRaises(TypeError, iadd, mock)
  89. mock.__iadd__ = add
  90. mock += 6
  91. self.assertEqual(mock, original)
  92. self.assertEqual(mock.value, 9)
  93. self.assertRaises(TypeError, lambda: 3 + mock)
  94. mock.__radd__ = add
  95. self.assertEqual(7 + mock, mock)
  96. self.assertEqual(mock.value, 16)
  97. def test_division(self):
  98. original = mock = Mock()
  99. mock.value = 32
  100. self.assertRaises(TypeError, lambda: mock / 2)
  101. def truediv(self, other):
  102. mock.value /= other
  103. return self
  104. mock.__truediv__ = truediv
  105. self.assertEqual(mock / 2, mock)
  106. self.assertEqual(mock.value, 16)
  107. del mock.__truediv__
  108. def itruediv(mock):
  109. mock /= 4
  110. self.assertRaises(TypeError, itruediv, mock)
  111. mock.__itruediv__ = truediv
  112. mock /= 8
  113. self.assertEqual(mock, original)
  114. self.assertEqual(mock.value, 2)
  115. self.assertRaises(TypeError, lambda: 8 / mock)
  116. mock.__rtruediv__ = truediv
  117. self.assertEqual(0.5 / mock, mock)
  118. self.assertEqual(mock.value, 4)
  119. def test_hash(self):
  120. mock = Mock()
  121. # test delegation
  122. self.assertEqual(hash(mock), Mock.__hash__(mock))
  123. def _hash(s):
  124. return 3
  125. mock.__hash__ = _hash
  126. self.assertEqual(hash(mock), 3)
  127. def test_nonzero(self):
  128. m = Mock()
  129. self.assertTrue(bool(m))
  130. m.__bool__ = lambda s: False
  131. self.assertFalse(bool(m))
  132. def test_comparison(self):
  133. mock = Mock()
  134. def comp(s, o):
  135. return True
  136. mock.__lt__ = mock.__gt__ = mock.__le__ = mock.__ge__ = comp
  137. self. assertTrue(mock < 3)
  138. self. assertTrue(mock > 3)
  139. self. assertTrue(mock <= 3)
  140. self. assertTrue(mock >= 3)
  141. self.assertRaises(TypeError, lambda: MagicMock() < object())
  142. self.assertRaises(TypeError, lambda: object() < MagicMock())
  143. self.assertRaises(TypeError, lambda: MagicMock() < MagicMock())
  144. self.assertRaises(TypeError, lambda: MagicMock() > object())
  145. self.assertRaises(TypeError, lambda: object() > MagicMock())
  146. self.assertRaises(TypeError, lambda: MagicMock() > MagicMock())
  147. self.assertRaises(TypeError, lambda: MagicMock() <= object())
  148. self.assertRaises(TypeError, lambda: object() <= MagicMock())
  149. self.assertRaises(TypeError, lambda: MagicMock() <= MagicMock())
  150. self.assertRaises(TypeError, lambda: MagicMock() >= object())
  151. self.assertRaises(TypeError, lambda: object() >= MagicMock())
  152. self.assertRaises(TypeError, lambda: MagicMock() >= MagicMock())
  153. def test_equality(self):
  154. for mock in Mock(), MagicMock():
  155. self.assertEqual(mock == mock, True)
  156. self.assertIsInstance(mock == mock, bool)
  157. self.assertEqual(mock != mock, False)
  158. self.assertIsInstance(mock != mock, bool)
  159. self.assertEqual(mock == object(), False)
  160. self.assertEqual(mock != object(), True)
  161. def eq(self, other):
  162. return other == 3
  163. mock.__eq__ = eq
  164. self.assertTrue(mock == 3)
  165. self.assertFalse(mock == 4)
  166. def ne(self, other):
  167. return other == 3
  168. mock.__ne__ = ne
  169. self.assertTrue(mock != 3)
  170. self.assertFalse(mock != 4)
  171. mock = MagicMock()
  172. mock.__eq__.return_value = True
  173. self.assertIsInstance(mock == 3, bool)
  174. self.assertEqual(mock == 3, True)
  175. mock.__ne__.return_value = False
  176. self.assertIsInstance(mock != 3, bool)
  177. self.assertEqual(mock != 3, False)
  178. def test_len_contains_iter(self):
  179. mock = Mock()
  180. self.assertRaises(TypeError, len, mock)
  181. self.assertRaises(TypeError, iter, mock)
  182. self.assertRaises(TypeError, lambda: 'foo' in mock)
  183. mock.__len__ = lambda s: 6
  184. self.assertEqual(len(mock), 6)
  185. mock.__contains__ = lambda s, o: o == 3
  186. self.assertIn(3, mock)
  187. self.assertNotIn(6, mock)
  188. mock.__iter__ = lambda s: iter('foobarbaz')
  189. self.assertEqual(list(mock), list('foobarbaz'))
  190. def test_magicmock(self):
  191. mock = MagicMock()
  192. mock.__iter__.return_value = iter([1, 2, 3])
  193. self.assertEqual(list(mock), [1, 2, 3])
  194. getattr(mock, '__bool__').return_value = False
  195. self.assertFalse(hasattr(mock, '__nonzero__'))
  196. self.assertFalse(bool(mock))
  197. for entry in _magics:
  198. self.assertTrue(hasattr(mock, entry))
  199. self.assertFalse(hasattr(mock, '__imaginary__'))
  200. def test_magic_mock_equality(self):
  201. mock = MagicMock()
  202. self.assertIsInstance(mock == object(), bool)
  203. self.assertIsInstance(mock != object(), bool)
  204. self.assertEqual(mock == object(), False)
  205. self.assertEqual(mock != object(), True)
  206. self.assertEqual(mock == mock, True)
  207. self.assertEqual(mock != mock, False)
  208. def test_asyncmock_defaults(self):
  209. mock = AsyncMock()
  210. self.assertEqual(int(mock), 1)
  211. self.assertEqual(complex(mock), 1j)
  212. self.assertEqual(float(mock), 1.0)
  213. self.assertNotIn(object(), mock)
  214. self.assertEqual(len(mock), 0)
  215. self.assertEqual(list(mock), [])
  216. self.assertEqual(hash(mock), object.__hash__(mock))
  217. self.assertEqual(str(mock), object.__str__(mock))
  218. self.assertTrue(bool(mock))
  219. self.assertEqual(round(mock), mock.__round__())
  220. self.assertEqual(math.trunc(mock), mock.__trunc__())
  221. self.assertEqual(math.floor(mock), mock.__floor__())
  222. self.assertEqual(math.ceil(mock), mock.__ceil__())
  223. self.assertTrue(iscoroutinefunction(mock.__aexit__))
  224. self.assertTrue(iscoroutinefunction(mock.__aenter__))
  225. self.assertIsInstance(mock.__aenter__, AsyncMock)
  226. self.assertIsInstance(mock.__aexit__, AsyncMock)
  227. # in Python 3 oct and hex use __index__
  228. # so these tests are for __index__ in py3k
  229. self.assertEqual(oct(mock), '0o1')
  230. self.assertEqual(hex(mock), '0x1')
  231. # how to test __sizeof__ ?
  232. def test_magicmock_defaults(self):
  233. mock = MagicMock()
  234. self.assertEqual(int(mock), 1)
  235. self.assertEqual(complex(mock), 1j)
  236. self.assertEqual(float(mock), 1.0)
  237. self.assertNotIn(object(), mock)
  238. self.assertEqual(len(mock), 0)
  239. self.assertEqual(list(mock), [])
  240. self.assertEqual(hash(mock), object.__hash__(mock))
  241. self.assertEqual(str(mock), object.__str__(mock))
  242. self.assertTrue(bool(mock))
  243. self.assertEqual(round(mock), mock.__round__())
  244. self.assertEqual(math.trunc(mock), mock.__trunc__())
  245. self.assertEqual(math.floor(mock), mock.__floor__())
  246. self.assertEqual(math.ceil(mock), mock.__ceil__())
  247. self.assertTrue(iscoroutinefunction(mock.__aexit__))
  248. self.assertTrue(iscoroutinefunction(mock.__aenter__))
  249. self.assertIsInstance(mock.__aenter__, AsyncMock)
  250. self.assertIsInstance(mock.__aexit__, AsyncMock)
  251. # in Python 3 oct and hex use __index__
  252. # so these tests are for __index__ in py3k
  253. self.assertEqual(oct(mock), '0o1')
  254. self.assertEqual(hex(mock), '0x1')
  255. # how to test __sizeof__ ?
  256. def test_magic_methods_fspath(self):
  257. mock = MagicMock()
  258. expected_path = mock.__fspath__()
  259. mock.reset_mock()
  260. self.assertEqual(os.fspath(mock), expected_path)
  261. mock.__fspath__.assert_called_once()
  262. def test_magic_methods_and_spec(self):
  263. class Iterable(object):
  264. def __iter__(self): pass
  265. mock = Mock(spec=Iterable)
  266. self.assertRaises(AttributeError, lambda: mock.__iter__)
  267. mock.__iter__ = Mock(return_value=iter([]))
  268. self.assertEqual(list(mock), [])
  269. class NonIterable(object):
  270. pass
  271. mock = Mock(spec=NonIterable)
  272. self.assertRaises(AttributeError, lambda: mock.__iter__)
  273. def set_int():
  274. mock.__int__ = Mock(return_value=iter([]))
  275. self.assertRaises(AttributeError, set_int)
  276. mock = MagicMock(spec=Iterable)
  277. self.assertEqual(list(mock), [])
  278. self.assertRaises(AttributeError, set_int)
  279. def test_magic_methods_and_spec_set(self):
  280. class Iterable(object):
  281. def __iter__(self): pass
  282. mock = Mock(spec_set=Iterable)
  283. self.assertRaises(AttributeError, lambda: mock.__iter__)
  284. mock.__iter__ = Mock(return_value=iter([]))
  285. self.assertEqual(list(mock), [])
  286. class NonIterable(object):
  287. pass
  288. mock = Mock(spec_set=NonIterable)
  289. self.assertRaises(AttributeError, lambda: mock.__iter__)
  290. def set_int():
  291. mock.__int__ = Mock(return_value=iter([]))
  292. self.assertRaises(AttributeError, set_int)
  293. mock = MagicMock(spec_set=Iterable)
  294. self.assertEqual(list(mock), [])
  295. self.assertRaises(AttributeError, set_int)
  296. def test_setting_unsupported_magic_method(self):
  297. mock = MagicMock()
  298. def set_setattr():
  299. mock.__setattr__ = lambda self, name: None
  300. self.assertRaisesRegex(AttributeError,
  301. "Attempting to set unsupported magic method '__setattr__'.",
  302. set_setattr
  303. )
  304. def test_attributes_and_return_value(self):
  305. mock = MagicMock()
  306. attr = mock.foo
  307. def _get_type(obj):
  308. # the type of every mock (or magicmock) is a custom subclass
  309. # so the real type is the second in the mro
  310. return type(obj).__mro__[1]
  311. self.assertEqual(_get_type(attr), MagicMock)
  312. returned = mock()
  313. self.assertEqual(_get_type(returned), MagicMock)
  314. def test_magic_methods_are_magic_mocks(self):
  315. mock = MagicMock()
  316. self.assertIsInstance(mock.__getitem__, MagicMock)
  317. mock[1][2].__getitem__.return_value = 3
  318. self.assertEqual(mock[1][2][3], 3)
  319. def test_magic_method_reset_mock(self):
  320. mock = MagicMock()
  321. str(mock)
  322. self.assertTrue(mock.__str__.called)
  323. mock.reset_mock()
  324. self.assertFalse(mock.__str__.called)
  325. def test_dir(self):
  326. # overriding the default implementation
  327. for mock in Mock(), MagicMock():
  328. def _dir(self):
  329. return ['foo']
  330. mock.__dir__ = _dir
  331. self.assertEqual(dir(mock), ['foo'])
  332. def test_bound_methods(self):
  333. m = Mock()
  334. # XXXX should this be an expected failure instead?
  335. # this seems like it should work, but is hard to do without introducing
  336. # other api inconsistencies. Failure message could be better though.
  337. m.__iter__ = [3].__iter__
  338. self.assertRaises(TypeError, iter, m)
  339. def test_magic_method_type(self):
  340. class Foo(MagicMock):
  341. pass
  342. foo = Foo()
  343. self.assertIsInstance(foo.__int__, Foo)
  344. def test_descriptor_from_class(self):
  345. m = MagicMock()
  346. type(m).__str__.return_value = 'foo'
  347. self.assertEqual(str(m), 'foo')
  348. def test_iterable_as_iter_return_value(self):
  349. m = MagicMock()
  350. m.__iter__.return_value = [1, 2, 3]
  351. self.assertEqual(list(m), [1, 2, 3])
  352. self.assertEqual(list(m), [1, 2, 3])
  353. m.__iter__.return_value = iter([4, 5, 6])
  354. self.assertEqual(list(m), [4, 5, 6])
  355. self.assertEqual(list(m), [])
  356. def test_matmul(self):
  357. m = MagicMock()
  358. self.assertIsInstance(m @ 1, MagicMock)
  359. m.__matmul__.return_value = 42
  360. m.__rmatmul__.return_value = 666
  361. m.__imatmul__.return_value = 24
  362. self.assertEqual(m @ 1, 42)
  363. self.assertEqual(1 @ m, 666)
  364. m @= 24
  365. self.assertEqual(m, 24)
  366. def test_divmod_and_rdivmod(self):
  367. m = MagicMock()
  368. self.assertIsInstance(divmod(5, m), MagicMock)
  369. m.__divmod__.return_value = (2, 1)
  370. self.assertEqual(divmod(m, 2), (2, 1))
  371. m = MagicMock()
  372. foo = divmod(2, m)
  373. self.assertIsInstance(foo, MagicMock)
  374. foo_direct = m.__divmod__(2)
  375. self.assertIsInstance(foo_direct, MagicMock)
  376. bar = divmod(m, 2)
  377. self.assertIsInstance(bar, MagicMock)
  378. bar_direct = m.__rdivmod__(2)
  379. self.assertIsInstance(bar_direct, MagicMock)
  380. # http://bugs.python.org/issue23310
  381. # Check if you can change behaviour of magic methods in MagicMock init
  382. def test_magic_in_initialization(self):
  383. m = MagicMock(**{'__str__.return_value': "12"})
  384. self.assertEqual(str(m), "12")
  385. def test_changing_magic_set_in_initialization(self):
  386. m = MagicMock(**{'__str__.return_value': "12"})
  387. m.__str__.return_value = "13"
  388. self.assertEqual(str(m), "13")
  389. m = MagicMock(**{'__str__.return_value': "12"})
  390. m.configure_mock(**{'__str__.return_value': "14"})
  391. self.assertEqual(str(m), "14")
  392. if __name__ == '__main__':
  393. unittest.main()