mock open for unit testing in python

2019-07-04 11:54发布

问题:

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?

回答1:

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.



回答2:

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.