You can use mock_open helper function:
unittest.mock.mock_open(mock=None, read_data=None)
A helper function to create a mock to replace the use of open(). It works for open() called directly or used as a context manager.
Previous sentences come from the documentation of the module unittest.mock
Because the production method get_version() reads a file by a for loop you have to define methods __iter__ and __next__ for the mock object instantiated by mock_open as suggested by this post.
So if your production code is stored in the file my_class.py as below:
class MyClass:
def get_version(self):
version = ''
with open("file_path") as openfile:
for line in openfile:
sline = line.split()
for row, column in enumerate(sline):
if column == "version=":
version = sline[row+1].strip('"')
return version
a possible test which uses the helper function mock_open could be the following:
from my_class import MyClass
import unittest
from unittest.mock import mock_open, patch
class TestMyClass(unittest.TestCase):
def test_get_version(self):
# by the argument read_data set the content of the file
mocked_open = mock_open(read_data='version= 2.1\nsecond line\n')
EXPECTED_VERSION = "2.1"
mocked_open_instance = mocked_open.return_value
mocked_open_instance.__iter__ = lambda self: self
mocked_open_instance.__next__ = lambda self: next(iter(self.readline, ''))
with patch('builtins.open', mocked_open):
sut = MyClass()
version = sut.get_version()
self.assertEqual(EXPECTED_VERSION, version)
mocked_open.assert_called_with('file_path')
# for the file content 'version= 2.1\nsecond line\n' the readline function must be called 3 times
self.assertEqual(3, mocked_open_instance.readline.call_count)
if __name__ == '__main__':
unittest.main()
Version of Python used is: Python 3.6.
exceptblock.open(). Have a look here as a starting point.