我正在使用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
,而直接调用它会返回我在mock_open.return_value
中定义的内容。有什么想法吗?
答案 0 :(得分:11)
对于已经实现文件接口的StringIO
对象来说,这听起来像是一个很好的用例。也许你可以制作一个file_mock = MagicMock(spec=file, wraps=StringIO('test'))
。或者您可以让您的函数接受类似文件的对象并将其传递给StringIO
而不是真实文件,从而避免需要进行丑陋的猴子修补。
你看过模拟文档吗?
答案 1 :(得分:10)
在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来返回文件内容。)
答案 2 :(得分:1)
以@ tbc0答案为基础,以支持Python 2和3(多版本测试对端口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())