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