获取mock的file.read()的实际返回值
我正在使用python-mock来模拟打开文件的操作。我希望能通过这种方式传入一些假数据,这样我就可以验证read()
是否被调用,同时在测试时不需要真的去访问文件系统。
这是我目前的代码:
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()
运行后得到的结果是<mock.Mock object at 0x8f4aaec>
,而不是我预期的'test'
。我在构建这个模拟的时候哪里出错了呢?
补充:
看起来像这样:
with open('x') as f:
f.read()
和这样:
f = open('x')
f.read()
是不同的对象。把模拟作为上下文管理器使用时,它会返回一个新的Mock
对象,而直接调用它则返回我在mock_open.return_value
中定义的内容。有什么想法吗?
3 个回答
2
在@tbc0的回答基础上,为了支持Python 2和3(同时测试这两个版本对将Python 2迁移到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())
31
在Python 3中,使用的模式很简单:
>>> 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
>>>
(是的,你甚至可以模拟/dev/null,让它返回文件内容。)
14
这听起来是一个很好的场景,可以使用一个叫做 StringIO
的对象,它已经具备了文件的功能。你可以这样做:file_mock = MagicMock(spec=file, wraps=StringIO('test'))
。或者,你也可以让你的函数接受一个类似文件的对象,然后传入一个 StringIO
,这样就不需要去做那些麻烦的修改了。
你有没有看过模拟(mock)的文档呢?