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