Skip to content

Commit d3ea46e

Browse files
authored
Merge pull request faif#186 from fkromer/constructor_injection
add: constructor injection
2 parents 520e9b1 + 4cca032 commit d3ea46e

File tree

4 files changed

+100
-0
lines changed

4 files changed

+100
-0
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
11
__pycache__
2+
*.pyc

dft/__init__.py

Whitespace-only changes.

dft/constructor_injection.py

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
#!/usr/bin/python
2+
# -*- coding : utf-8 -*-
3+
import datetime
4+
5+
"""
6+
Port of the Java example of "Constructor Injection" in
7+
"xUnit Test Patterns - Refactoring Test Code" by Gerard Meszaros
8+
(ISBN-10: 0131495054, ISBN-13: 978-0131495050) accessible in outdated version on
9+
http://xunitpatterns.com/Dependency%20Injection.html.
10+
11+
production code which is untestable:
12+
13+
class TimeDisplay(object):
14+
15+
def __init__(self):
16+
self.time_provider = datetime.datetime
17+
18+
def get_current_time_as_html_fragment(self):
19+
current_time = self.time_provider.now()
20+
current_time_as_html_fragment = "<span class=\"tinyBoldText\">" + current_time.hour + ":" + current_time.minute + "</span>"
21+
return current_time_as_html_fragment
22+
"""
23+
24+
class TimeDisplay(object):
25+
26+
def __init__(self, time_provider):
27+
self.time_provider = time_provider
28+
29+
def get_current_time_as_html_fragment(self):
30+
current_time = self.time_provider.now()
31+
current_time_as_html_fragment = "<span class=\"tinyBoldText\">" + current_time + "</span>"
32+
return current_time_as_html_fragment
33+
34+
class ProductionCodeTimeProvider(object):
35+
"""
36+
Production code version of the time provider (just a wrapper for formatting
37+
datetime for this example).
38+
"""
39+
40+
def now(self):
41+
current_time = datetime.datetime.now()
42+
current_time_formatted = str(current_time.hour) + ":" + str(current_time.minute)
43+
return current_time_formatted
44+
45+
class MidnightTimeProvider(object):
46+
"""
47+
Class implemented as hard-coded stub (in contrast to configurable stub).
48+
"""
49+
50+
def now(self):
51+
current_time_is_always_midnight = "24:01"
52+
return current_time_is_always_midnight

tests/test_constructor_injection.py

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
#!/usr/bin/env python
2+
# -*- coding: utf-8 -*-
3+
import unittest
4+
5+
from dft.constructor_injection import TimeDisplay, MidnightTimeProvider, ProductionCodeTimeProvider, datetime
6+
7+
"""
8+
Port of the Java example of "Constructor Injection" in
9+
"xUnit Test Patterns - Refactoring Test Code" by Gerard Meszaros
10+
(ISBN-10: 0131495054, ISBN-13: 978-0131495050) accessible in outdated version on
11+
http://xunitpatterns.com/Dependency%20Injection.html.
12+
13+
Test code which will almost always fail (if not exactly 12:01) when untestable
14+
production code (have a look into constructor_injection.py) is used:
15+
16+
def test_display_current_time_at_midnight(self):
17+
class_under_test = TimeDisplay()
18+
expected_time = "24:01"
19+
result = class_under_test.get_current_time_as_as_html_fragment()
20+
self.assertEqual(result, expected_time)
21+
"""
22+
23+
class ConstructorInjectionTest(unittest.TestCase):
24+
25+
def test_display_current_time_at_midnight(self):
26+
"""
27+
Would almost always fail (despite of right at/after midnight) if
28+
untestable production code would have been used.
29+
"""
30+
time_provider_stub = MidnightTimeProvider()
31+
class_under_test = TimeDisplay(time_provider_stub)
32+
expected_time = "<span class=\"tinyBoldText\">24:01</span>"
33+
self.assertEqual(class_under_test.get_current_time_as_html_fragment(), expected_time)
34+
35+
def test_display_current_time_at_current_time(self):
36+
"""
37+
Just as justification for working example with the time provider used in
38+
production. (Will always pass.)
39+
"""
40+
production_code_time_provider = ProductionCodeTimeProvider()
41+
class_under_test = TimeDisplay(production_code_time_provider)
42+
current_time = datetime.datetime.now()
43+
expected_time = "<span class=\"tinyBoldText\">{}:{}</span>".format(current_time.hour, current_time.minute)
44+
self.assertEqual(class_under_test.get_current_time_as_html_fragment(), expected_time)
45+
46+
if __name__ == "__main__":
47+
unittest.main()

0 commit comments

Comments
 (0)