I would like to test, using unittest, a method which reads from a file using a context manager:
with open(k_file, 'r') as content_file:
content = content_file.read()
I don't want to have to create a file on my system so I wanted to mock it, but I'm not suceeding much at the moment. I've found mock_open but I don't really understand how I'm supposed to use it and feed the mock as content_file in my test case. There is for instance this post here, but I do not understand how one is supposed to write this in a test case without modifying the original code.
Could anyone point me in the right direction?
mock_open()
is the way to go; you patch open
in your code-under-test with the result of a mock_open()
call:
mocked_open = unittest.mock.mock_open(read_data='file contents\nas needed\n')
with unittest.mock.patch('yourmodule.open', mocked_open, create=True):
# tests calling your code; the open function will use the mocked_open object
The patch()
context manager will put a open()
global into your module (I named it yourmodule
), bound to the mocked_open()
-produced object. This object will pretend to produce a file object when called.
The only thing this mock file object won't do yet is iteration; you cannot do for line in content_file
with it, at least not in current versions of the mock
library. See Customizing unittest.mock.mock_open for iteration for a work-around.
An alternative is pyfakefs. It allows you to create a fake file system, write and read files, set permissions and more without ever touching your real disk. It also contains a practical example and tutorial showing how to apply pyfakefs to both unittest and doctest.