1
1
import unittest
2
2
from unittest .mock import mock_open , patch
3
+ from contextlib import contextmanager
4
+ from io import StringIO
3
5
import solution
4
6
5
7
8
+ class NotMocked (Exception ):
9
+ def __init__ (self , filename ):
10
+ super (NotMocked , self ).__init__ (
11
+ "The file %s was opened, but not mocked." % filename )
12
+ self .filename = filename
13
+
14
+
15
+ @contextmanager
16
+ def mock_open (filename , contents = None , complain = True ):
17
+ """Mock the open() builtin function on a specific filename
18
+ .
19
+ Let execution pass through to open() on files different than
20
+ :filename:. Return a StringIO with :contents: if the file was
21
+ matched. If the :contents: parameter is not given or if it is None,
22
+ a StringIO instance simulating an empty file is returned.
23
+ .
24
+ If :complain: is True (default), will raise an AssertionError if
25
+ :filename: was not opened in the enclosed block. A NotMocked
26
+ exception will be raised if open() was called with a file that was
27
+ not mocked by mock_open.
28
+
29
+ Source: https://mapleoin.github.io/perma/mocking-python-file-open
30
+ """
31
+ open_files = set ()
32
+
33
+ def mock_file (* args ):
34
+ if args [0 ] == filename :
35
+ f = StringIO (contents )
36
+ f .name = filename
37
+ else :
38
+ mocked_file .stop ()
39
+ f = open (* args )
40
+ mocked_file .start ()
41
+ open_files .add (f .name )
42
+ return f
43
+
44
+ mocked_file = patch ('builtins.open' , mock_file )
45
+ mocked_file .start ()
46
+ try :
47
+ yield
48
+ except NotMocked as e :
49
+ if e .filename != filename :
50
+ raise
51
+ mocked_file .stop ()
52
+ try :
53
+ open_files .remove (filename )
54
+ except KeyError :
55
+ if complain :
56
+ raise AssertionError ("The file %s was not opened." % filename )
57
+ for f_name in open_files :
58
+ if complain :
59
+ raise NotMocked (f_name )
60
+
61
+
6
62
class Test (unittest .TestCase ):
7
63
def __init__ (self , * args , ** kwargs ):
8
64
super (Test , self ).__init__ (* args , ** kwargs )
@@ -17,8 +73,7 @@ def tearDown(self):
17
73
print ("" )
18
74
19
75
def execute_test (self , test_input ):
20
- mocked_open_function = mock_open (read_data = test_input )
21
- with patch ("builtins.open" , mocked_open_function ):
76
+ with mock_open ('/input.txt' , test_input , False ):
22
77
self .solution .calculate (True )
23
78
24
79
def get_solution (self , nr ):
0 commit comments