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