Getting an actual return value for a mocked file.read()
Solution 1
This sounds like a good use-case for a StringIO
object that already implements the file interface. Maybe you can make a file_mock = MagicMock(spec=file, wraps=StringIO('test'))
. Or you could just have your function accept a file-like object and pass it a StringIO
instead of a real file, avoiding the need for ugly monkey-patching.
Have you looked the mock documentation?
Solution 2
In Python 3 the pattern is simply:
>>> import unittest.mock as um
>>> with um.patch('builtins.open', um.mock_open(read_data='test')):
... with open('/dev/null') as f:
... print(f.read())
...
test
>>>
(Yes, you can even mock /dev/null to return file contents.)
Solution 3
building on @tbc0 answer, to support Python 2 and 3 (multi-version tests are helpful to port 2 to 3):
import sys
module_ = "builtins"
module_ = module_ if module_ in sys.modules else '__builtin__'
try:
import unittest.mock as mock
except (ImportError,) as e:
import mock
with mock.patch('%s.open' % module_, mock.mock_open(read_data='test')):
with open('/dev/null') as f:
print(f.read())
Brian Hicks
Updated on July 08, 2020Comments
-
Brian Hicks almost 4 years
I'm using python-mock to mock out a file open call. I would like to be able to pass in fake data this way, so I can verify that
read()
is being called as well as using test data without hitting the filesystem on tests.Here's what I've got so far:
file_mock = MagicMock(spec=file) file_mock.read.return_value = 'test' with patch('__builtin__.open', create=True) as mock_open: mock_open.return_value = file_mock with open('x') as f: print f.read()
The output of this is
<mock.Mock object at 0x8f4aaec>
intead of'test'
as I would assume. What am I doing wrong in constructing this mock?Edit:
Looks like this:
with open('x') as f: f.read()
and this:
f = open('x') f.read()
are different objects. Using the mock as a context manager makes it return a new
Mock
, whereas calling it directly returns whatever I've defined inmock_open.return_value
. Any ideas? -
Brian Hicks over 12 yearsI tried messing around some with this. It appears that mock_open is return a different object when used in a context manager versus being called directly. I've updated my question. Any ideas?
-
Brian Hicks over 12 yearsI read the top half of that page, but skipped the bottom half for some unknown reason. Herp and derp.
-
Godfrey almost 4 yearsYou can use the six library to import
builtins
six.readthedocs.io/… -
Vad1mo over 2 yearsIf the website would be still up to this date, that would be helpful. Now the answer becomes a bit useless.