Skip to content

Commit 558b9c4

Browse files
committed
Unit Test: Mock the open() builtin function on a specific filename
- input.txt gets mocked by test_input - All other files (like JSON) do not get mocked
1 parent c68b73f commit 558b9c4

File tree

1 file changed

+57
-2
lines changed

1 file changed

+57
-2
lines changed

lib/test.py

Lines changed: 57 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,64 @@
11
import unittest
22
from unittest.mock import mock_open, patch
3+
from contextlib import contextmanager
4+
from io import StringIO
35
import solution
46

57

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+
662
class Test(unittest.TestCase):
763
def __init__(self, *args, **kwargs):
864
super(Test, self).__init__(*args, **kwargs)
@@ -17,8 +73,7 @@ def tearDown(self):
1773
print("")
1874

1975
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):
2277
self.solution.calculate(True)
2378

2479
def get_solution(self, nr):

0 commit comments

Comments
 (0)