Skip to content

Instantly share code, notes, and snippets.

@iartarisi
Created November 15, 2012 14:28
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save iartarisi/4078879 to your computer and use it in GitHub Desktop.
Save iartarisi/4078879 to your computer and use it in GitHub Desktop.
mock open file
@contextmanager
def mock_open(filename, contents=None, complain=True):
"""Mock __builtin__.open() on a specific filename
Let execution pass through to __builtin__.open() on other
files. Return a BytesIO with :contents: if the file was matched. If
the :contents: parameter is not given or if it None, a BytesIO
instance simulating an empty file is returned.
If :complain: is True (default). Will raise an error if a
__builtin__.open was called with a file that was not mocked.
"""
open_files = [] # simulate non-local scope with mutable lists
def mock_file(*args):
if args[0] == filename:
r = BytesIO(contents)
r.name = filename
else:
mocked_file.stop()
r = open(*args)
mocked_file.start()
open_files.append(r)
return r
mocked_file = mock.patch('__builtin__.open', mock_file)
mocked_file.start()
try:
yield
except NotMocked as e:
if e.filename != filename:
raise
mocked_file.stop()
found = False
for f in open_files:
f.close()
if f.name == filename:
found = f
elif complain:
raise NotMocked(f.name)
if not found:
raise AssertionError("The file %s was not opened." % filename)
class NotMocked(Exception):
def __init__(self, filename):
super(NotMocked, self).__init__(
"The file %s was opened, but not mocked." % filename)
self.filename = filename
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment