1from io import StringIO
2from unittest.mock import PropertyMock
3import pytest
4
5from mocker_builder import MockerBuilder
6from test_cases import my_heroes
7from test_cases.my_heroes import (
8 Batman,
9 HobbyHero,
10 IHero,
11 JusticeLeague,
12 OtherHero,
13 PeakyBlinder,
14 MyHeroes,
15 Robin
16)
17
18
19def print_io_test():
20 print("Ouieh!!!")
21
22
23class Foo(IHero):
24 nickname: str = "Bob"
25
26 def eating_banana(self) -> str:
27 return "have no banana"
28
29 def wearing_pyjama(self) -> str:
30 return "have no pyjama"
31
32 def just_call_for(self) -> str:
33 return "Bob Foo"
34
35 def just_says(self) -> str:
36 return "foo foo"
37
38
39class TestMyHeroes(MockerBuilder):
40 """Main Test Class to implement MockerBuilder features to make your tests"""
41
42 @MockerBuilder.initializer
43 def mocker_builder_setup(self):
44 # ================== Setting fixtures ===================
45 self.my_hero = self.add_fixture(
46 content=lambda: (yield PeakyBlinder(
47 bananas=12,
48 pyjamas=7,
49 nickname="Thomas Shelby"
50 ))
51 )
52 # =================== Setting mocks ======================
53 self.what_i_do_when_nobody_is_looking = self.patch(
54 PeakyBlinder,
55 'what_i_do_when_nobody_is_looking',
56 return_value=HobbyHero("I just drink wisky")
57 )
58 self.get_my_hero_hobby = self.patch(
59 Robin,
60 'get_my_hero_hobby',
61 return_value=HobbyHero("I just watch TV")
62 )
63 self.mock_my_heroes_module = self.patch(
64 target=my_heroes.initialize_other_hero
65 )
66 self.mock_my_hero_attribue = self.patch(
67 target=MyHeroes,
68 attribute='_my_hero',
69 mock_configure={
70 'eating_banana.return_value': "Banana Noooo!",
71 'just_says.side_effect': ["Nothing to say!"]
72 }
73 )
74 self.mock_other_hero = self.patch(
75 target=OtherHero,
76 mock_configure={
77 'return_value.just_says.return_value': "He feels good!"
78 }
79 )
80 self.my_hero_batman = self.patch(
81 # XXX or target='main.Batman' to mock the Batman class imported from here.
82 target=Batman,
83 mock_configure={
84 'return_value.nickname': 'Bat Mock',
85 'return_value.eating_banana.return_value': "doesn't like banana",
86 'return_value.wearing_pyjama.return_value': "doesn't wear pyjama",
87 'return_value.just_call_for.return_value': "just calls for Mocker",
88 'return_value.just_says.return_value': "I'm gonna mock you babe!",
89 }
90 )
91 self.mock_justice_league__init__ = self.patch(
92 target=JusticeLeague.__init__
93 )
94 # ========================================================
95
96 def test_io(self):
97 self.test_print_io = self.patch(
98 target='sys.stdout',
99 new_callable=StringIO
100 # spec=StringIO
101 )
102 print_io_test()
103 # assert self.test_print_io.mock.called
104 assert self.test_print_io.mock.getvalue() == 'Ouieh!!!\n'
105
106 def test_another_print_io(self):
107 self.test_print_io = self.patch(
108 target='sys.stdout',
109 new_callable=StringIO
110 )
111 patched_print_io_test = self.patch(
112 target=print_io_test,
113 side_effect=[print("Ooouuiieeh!!")]
114 )
115 print_io_test()
116 assert not self.test_print_io.mock.getvalue() == 'Ouieh!!!\n'
117 assert self.test_print_io.mock.getvalue() == 'Ooouuiieeh!!\n'
118 patched_print_io_test.mock.assert_called()
119
120 def test_robin_becomes_batman(self):
121 self.robin_becomes_batman = self.patch(
122 Robin,
123 new=Batman
124 )
125 robin = Robin()
126 assert robin.nickname == "Little Bastard"
127
128 robin.nickname = "Bat Robinson"
129 assert not self.robin_becomes_batman.mock.nickname == "Bat Robinson"
130 assert self.robin_becomes_batman.mock.nickname == "Big Fat Bat"
131
132 # self.robin_becomes_batman.stop()
133 assert not robin.nickname == "Little Bastard"
134 assert robin.nickname == "Bat Robinson"
135
136 @pytest.mark.asyncio
137 async def test_what_i_do_when_nobody_is_looking(self):
138 # ----------------------- PeakyBlinder ----------------------
139 him = MyHeroes()
140 him.my_hero = PeakyBlinder(
141 my_hobby=HobbyHero(
142 what_i_do="Shot someone"
143 )
144 )
145 peaky_blinder = await him.what_my_hero_does_when_nobody_is_looking()
146
147 assert self.what_i_do_when_nobody_is_looking.mock.called
148 assert not peaky_blinder.what_i_do == "Shot someone"
149 assert peaky_blinder.what_i_do == "I just drink wisky"
150 assert him.does() == "Shot someone"
151 assert not him.does() == "I just drink wisky"
152
153 self.what_i_do_when_nobody_is_looking.set_result(
154 return_value=HobbyHero("Just relax!")
155 )
156 peaky_blinder = await him.what_my_hero_does_when_nobody_is_looking()
157
158 assert not peaky_blinder.what_i_do == "I just drink wisky"
159 assert peaky_blinder.what_i_do == "Just relax!"
160 assert him.does() == "Shot someone"
161 assert not him.does() == "just relax!"
162
163 # ----------------------- Robin ----------------------
164 robs = MyHeroes()
165 robs.my_hero = Robin(
166 my_hobby=HobbyHero(
167 what_i_do="I catch bad guys"
168 )
169 )
170 robin = await robs.what_my_hero_does_when_nobody_is_looking()
171
172 assert not self.get_my_hero_hobby.mock.called
173 assert not robin.what_i_do == "I just watch TV"
174 assert robin.what_i_do == "I catch bad guys"
175
176 # calling does() method calls mocked Robin.get_my_hero_hobby method so get the mocked value
177 assert not robs.does() == "I catch bad guys"
178 assert robs.does() == "I just watch TV"
179 assert self.get_my_hero_hobby.mock.called
180 assert self.get_my_hero_hobby.mock.call_count == 2
181
182 # ================================================================================
183 # -------------------- Robin -> Batman --------------------
184 self.robin_becomes_batman = self.patch(
185 Robin,
186 new=Batman
187 )
188 self.get_my_hero_hobby.stop()
189
190 # Here now we will actually mock Batman.get_my_hero_hobby calling
191 self.get_my_hero_hobby = self.patch(
192 Robin,
193 'get_my_hero_hobby',
194 return_value=HobbyHero("I just watch TV")
195 )
196 robs = MyHeroes()
197 robs.my_hero = Robin(
198 my_hobby=HobbyHero(
199 what_i_do="I catch bad guys"
200 )
201 )
202 robin = await robs.what_my_hero_does_when_nobody_is_looking()
203
204 assert not self.get_my_hero_hobby.mock.called
205 assert not robin.what_i_do == "I just watch TV"
206 assert robin.what_i_do == "I catch bad guys"
207
208 # calling does() method calls mocked Batman.get_my_hero_hobby method so get the mocked value
209 assert robs.does() == "I catch bad guys"
210 assert not robs.does() == "I just watch TV"
211 assert not self.get_my_hero_hobby.mock.called
212 assert self.get_my_hero_hobby.mock.call_count == 0
213
214 # ----------------------------------------------------------------
215 # remember we mocked robin as batman => self.robin_becomes_batman
216 # ----------------------------------------------------------------
217 bats = MyHeroes()
218 bats.my_hero = Batman(
219 my_hobby=HobbyHero(
220 what_i_do="I catch bad guys"
221 )
222 )
223 batman = await robs.what_my_hero_does_when_nobody_is_looking()
224
225 assert not self.get_my_hero_hobby.mock.called
226 assert not batman.what_i_do == "I just watch TV"
227 assert batman.what_i_do == "I catch bad guys"
228 assert bats.does() == "I just watch TV"
229 assert not bats.does() == "I catch bad guys"
230 assert self.get_my_hero_hobby.mock.called
231 assert self.get_my_hero_hobby.mock.call_count == 2
232
233 @pytest.mark.asyncio
234 async def test_heroes_sleeping(self):
235 justce_league = JusticeLeague()
236 assert self.mock_justice_league__init__().called
237
238 async def hero_names():
239 yield Batman().nickname
240 yield Robin().nickname
241 _hero_names = hero_names()
242
243 async for result in justce_league.are_heroes_sleeping():
244 assert result == "=== Heroes are awakened ==="
245
246 self.mock_justice_league__init__.stop()
247 justce_league = JusticeLeague()
248
249 async for result in justce_league.are_heroes_sleeping():
250 _hero_name = await _hero_names.__anext__()
251 print(result, _hero_name)
252 assert result == f"MagicMock=>({_hero_name}): ZZzzzz"
253
254 @pytest.mark.asyncio
255 async def test_call_heroes(self):
256 # Remember that JusticeLeague.__init__ still mocked, so calling JusticeLeague() doesn't
257 # initialize JusticeLeague._heroes attribute.
258
259 justce_league = JusticeLeague()
260 assert await justce_league.call_everybody() == "Uuhmm! Nobody here!"
261
262 with pytest.raises(AttributeError) as ex:
263 justce_league.join_hero(Batman())
264 assert "'JusticeLeague' object has no attribute '_heroes'" == str(ex.value)
265
266 # We just stop mocking JusticeLeague.__init__ to test a different behavior below
267 self.mock_justice_league__init__.stop()
268 del justce_league
269
270 with self.patch(
271 JusticeLeague,
272 '_heroes',
273 create=True,
274 return_value=PropertyMock(spec=list, return_value=[])
275 ):
276
277 justce_league = JusticeLeague()
278 justce_league.join_hero(Batman())
279 # my_heroes.Batman() still mocked
280 justce_league.join_hero(my_heroes.Batman())
281
282 assert await justce_league.call_everybody() == [
283 ('Batman', 'Come on', 'Big Fat Bat'),
284 ('MagicMock', 'Come on', 'Bat Mock')
285 ]
286
287 def test_mock_my_heroes_class(self):
288 mock_my_heroes_class = self.patch(
289 target=MyHeroes
290 )
291 my_heroes.who_is_the_best_hero()
292 assert mock_my_heroes_class().called
293
294 def test_mock_my_heroes_module(self):
295 self.mock_my_heroes_module.stop()
296 my_heroes.who_is_the_best_hero()
297 assert not self.mock_my_heroes_module().called
298
299 self.mock_my_heroes_module.start()
300 my_heroes.who_is_the_best_hero()
301 assert self.mock_my_heroes_module().called
302
303 def test_mock_my_hero_attribute(self):
304 assert self.mock_my_hero_attribue().eating_banana() == "Banana Noooo!"
305 assert self.mock_my_hero_attribue.mock.just_says() == "Nothing to say!"
306
307 def test_mock_my_class(self):
308 response = my_heroes.asks_what_other_hero_have_to_say_about_been_hero()
309 assert response == "He feels good!"
310
311 def test_my_hero_batman(self):
312 my_heroes.who_is_my_hero(Batman())
313
314 testing = MyHeroes()
315 testing.my_hero = my_heroes.Batman()
316 testing.who_is_my_hero()
317
318 assert self.my_hero_batman.mock.return_value.nickname == 'Bat Mock'
319 assert testing.my_hero.nickname == 'Bat Mock'
320
321 def test_mock_justice_league__init__(self):
322 justce_league = JusticeLeague()
323 assert justce_league.show_heroes() == "Opss! No heroes over here!"
324 assert justce_league.what_heroes_does() == "Eita! Heroes are doing nothing!"
325
326 self.mock_justice_league__init__.stop()
327
328 justce_league = JusticeLeague()
329 # my_heroes.Batman() is mocked
330 justce_league.join_hero(my_heroes.Batman())
331 justce_league.join_hero(Robin())
332
333 mock_test_io = self.patch(
334 target='sys.stdout',
335 new_callable=StringIO
336 )
337 justce_league.show_heroes()
338 expected = """MagicMock just calls for Mocker
339Robin just calls for Little Bastard\n"""
340 assert mock_test_io().getvalue() == expected
341
342 justce_league.what_heroes_does()
343 expected += """===========================
344Bat Mock
345doesn't like banana
346doesn't wear pyjama
347I'm gonna mock you babe!
348===========================
349Little Bastard
350is eating 1 banana(s)
351is wearing 4 pyjama(s)
352I'm gonna have a pint!\n"""
353 assert mock_test_io().getvalue() == expected
354
355 mock_test_io.stop()
356 self.mock_justice_league__init__.start()
357
358 justce_league = JusticeLeague()
359 assert justce_league.show_heroes() == "Opss! No heroes over here!"
360 assert justce_league.what_heroes_does() == "Eita! Heroes are doing nothing!"
361
362 def test_mock_ugly_hero(self):
363
364 assert my_heroes.UGLY_HERO == 'Me'
365
366 mock_ugly_hero = self.patch(
367 target=my_heroes,
368 attribute='UGLY_HERO',
369 mock_configure={
370 'third': 'You',
371 'who_is_the_most_ugly.return_value': 'Me again',
372 },
373 first='Batman',
374 second='Robin',
375 call_me_a_hero=lambda: PeakyBlinder().nickname
376 )
377 mock_ugly_hero.configure_mock(
378 fourth='Me',
379 **{
380 'who_is_my_hero.return_value': Batman().nickname,
381 'who_is_the_most_beautiful.side_effect': ValueError("There isn't any beautiful hero")
382 }
383 )
384
385 assert mock_ugly_hero().first == 'Batman'
386 assert mock_ugly_hero().second == 'Robin'
387 assert mock_ugly_hero().third == 'You'
388 assert mock_ugly_hero().fourth == 'Me'
389 assert mock_ugly_hero().who_is_the_most_ugly() == 'Me again'
390 assert mock_ugly_hero().call_me_a_hero() == "Bart Burp"
391 assert mock_ugly_hero().who_is_my_hero() == "Big Fat Bat"
392
393 with pytest.raises(ValueError) as ex:
394 mock_ugly_hero().who_is_the_most_beautiful()
395 assert "There isn't any beautiful hero" == str(ex.value)
396
397 def test_how_can_we_call_for_heores(self):
398 self.mock_justice_league__init__.stop()
399 self.my_hero_batman.stop()
400
401 justce_league = JusticeLeague()
402 # my_heroes.Batman() is mocked but was stopped
403 justce_league.join_hero(my_heroes.Batman())
404 justce_league.join_hero(Robin())
405 assert justce_league.how_can_we_call_for_heores() == [
406 ("Batman", "just calls for Big Fat Bat"),
407 ("Robin", "just calls for Little Bastard")
408 ]
409 self.mock_justice_league__init__.start()
410 justce_league = JusticeLeague()
411 assert self.mock_justice_league__init__().called
412 assert justce_league.how_can_we_call_for_heores() == "Opss! No heroes over here to call for!"
413
414 self.my_hero_batman.start()
415 self.mock_justice_league__init__.stop()
416
417 justce_league = JusticeLeague()
418 # my_heroes.Batman() is mocked and was started again
419 justce_league.join_hero(my_heroes.Batman())
420 justce_league.join_hero(Robin())
421 assert justce_league.how_can_we_call_for_heores() == [
422 ("MagicMock", "just calls for Mocker"),
423 ("Robin", "just calls for Little Bastard")
424 ]
425 assert self.my_hero_batman.mock.called
426
427 def test_my_hero_robin(self):
428 my_hero_robin = self.patch(
429 target=Robin(), # XXX we can mock from object instance! Ouieh!
430 return_value=PropertyMock(
431 nickname='Bastard Mock',
432 eating_banana=lambda: "eat a lot of bananas",
433 wearing_pyjama=lambda: "likes to be naked",
434 just_call_for=lambda: "Little Mocker",
435 just_says=lambda: "Mock me baby!"
436 )
437 )
438
439 my_heroes.who_is_my_hero(Robin())
440 testing = MyHeroes()
441 testing.my_hero = my_heroes.Robin()
442 testing.who_is_my_hero()
443
444 assert my_hero_robin.mock.called
445 assert my_hero_robin.mock.return_value.nickname == 'Bastard Mock'
446 assert my_hero_robin.mock.return_value.eating_banana() == "eat a lot of bananas"
447 assert my_hero_robin.mock.return_value.wearing_pyjama() == "likes to be naked"
448 assert my_hero_robin.mock.return_value.just_call_for() == "Little Mocker"
449 assert my_hero_robin.mock.return_value.just_says() == "Mock me baby!"
450
451 def test_set_result_return_value(self):
452 my_hero_robin = self.patch(
453 target=Robin,
454 return_value=Foo()
455 )
456
457 print("--------------------------------------------------------------------------")
458 print("Who is my hero:")
459 print("--------------------------------------------------------------------------")
460 my_heroes.who_is_my_hero(Robin())
461
462 testing = MyHeroes()
463 testing.my_hero = my_heroes.Robin()
464 print("--------------------------------------------------------------------------")
465 print("Who is my mocked hero with return_value = Foo():")
466 print("--------------------------------------------------------------------------")
467 testing.who_is_my_hero()
468
469 assert my_hero_robin.mock.called
470 assert isinstance(my_hero_robin.mock.return_value, Foo)
471
472 print("--------------------------------------------------------------------------")
473 print("Setting mock result return_value=PeakyBlinder()")
474 print("--------------------------------------------------------------------------")
475 my_hero_robin.set_result(
476 return_value=PeakyBlinder()
477 )
478 assert not isinstance(my_hero_robin.mock.return_value, Foo)
479 assert isinstance(my_hero_robin.mock.return_value, PeakyBlinder)
480
481 testing = MyHeroes()
482 testing.my_hero = my_heroes.Robin()
483 print("--------------------------------------------------------------------------")
484 print("Who is my mocked hero with return_value = PeakyBlinder():")
485 print("--------------------------------------------------------------------------")
486 testing.who_is_my_hero()
487
488 def test_set_result_side_effect(self):
489 my_hero_robin = self.patch(
490 target=PeakyBlinder,
491 side_effect=lambda: Foo()
492 )
493
494 print("--------------------------------------------------------------------------")
495 print("Who is my hero:")
496 print("--------------------------------------------------------------------------")
497 my_heroes.who_is_my_hero(PeakyBlinder())
498
499 testing = MyHeroes()
500 testing.my_hero = my_heroes.PeakyBlinder()
501 print("--------------------------------------------------------------------------")
502 print("Who is my mocked hero with side_effect = Foo():")
503 print("--------------------------------------------------------------------------")
504 testing.who_is_my_hero()
505
506 assert my_hero_robin.mock.called
507 assert isinstance(testing.my_hero, Foo)
508
509 print("--------------------------------------------------------------------------")
510 print("""Setting mock result side_effect=[
511 OtherHero(),
512 TypeError('Ops! No hero like that!')
513]""")
514 print("--------------------------------------------------------------------------")
515 my_hero_robin.set_result(
516 side_effect=[OtherHero(), TypeError("Ops! No hero like that!")]
517 )
518 testing.my_hero = my_heroes.PeakyBlinder()
519
520 assert not isinstance(testing.my_hero, Foo)
521 assert isinstance(testing.my_hero, OtherHero)
522
523 print("--------------------------------------------------------------------------")
524 print("Who is my mocked hero with side_effect = OtherHero():")
525 print("--------------------------------------------------------------------------")
526 testing.who_is_my_hero()
527
528 print("--------------------------------------------------------------------------")
529 print("Testing side_effect = TypeError('Ops! No hero like that!')")
530 print("--------------------------------------------------------------------------")
531 with pytest.raises(TypeError) as ex:
532 testing.my_hero = my_heroes.PeakyBlinder()
533 testing.who_is_my_hero()
534 assert "Ops! No hero like that!" == str(ex.value)
535
536 def test_create_my_heroes_method_runtime(self):
537 runtime_method = self.patch(
538 target=MyHeroes,
539 method='runtime_method',
540 create=True,
541 # return_value="Ouieh! I'm runtime method running...", # Also works
542 # mock_configure={
543 # 'return_value': "Ouieh! I'm runtime created method running..." # Also works
544 # },
545 )
546 runtime_method.configure_mock(
547 return_value="Ouieh! I'm runtime created method running..."
548 )
549 _my_heroes = MyHeroes()
550 _my_heroes.run_created_runtime_method()
551 assert runtime_method.mock.called