Mocking iteration over file in Python

Posted on Sat 24 December 2011 in Coding

Let’s say that I want to mock reading from a file using file’s iterator capability, i.e. (simplified version):

def readfile(f):
    using open(f) as fd:
        for line in fd:
            yield line

I could mock the readfile function, but then my mock would have to replicate the functionality of readfile, which as noted is somewhat more complicated than the version above. Luckily, mock allows us to mock the open function directly! The example in the documentation is a little short on details, though. Here’s how to setup the mock for the iterator case:

open_name = ""
with patch(open_name, create=True) as open_mock:
    open_mock.return_value = MagicMock(spec=file)
    handle = open_mock.return_value.__enter__.return_value
    handle.__iter__.return_value = iter(splitkeepsep(file_contents, "\n"))

The file_contents variable should contain the text of the file that’s being mocked away, and the splitkeepsep function looks like this (see also this post):

def splitkeepsep(s, sep):
    return reduce(lambda acc, i: acc[:-1] + [acc[-1] + i] if i == sep else acc + [i], re.split("(%s)" % re.escape(sep), s), [])

That’s all there is to it! Happy mocking!