获取模拟文件.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()

正如我所假设的,它的输出是'test'<mock.Mock object at 0x8f4aaec>整数。我在构建这个模型时做错了什么?

编辑:

看起来像这样:

with open('x') as f:
     f.read()

这个:

f = open('x')
f.read()

是不同的对象。使用mock作为上下文管理器会使它返回一个新的Mock,而直接调用它会返回我在mock_open.return_value中定义的任何内容。有什么想法吗?

在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来返回文件内容。)

对于已经实现文件接口的StringIO对象来说,这听起来是一个很好的用例。也许你可以做一个file_mock = MagicMock(spec=file, wraps=StringIO('test'))。或者,您可以让您的函数接受一个类似文件的对象,并向它传递一个StringIO,而不是一个真正的文件,从而避免了丑陋的猴子补丁的需要。

你看过模拟文件了吗?

http://www.voidspace.org.uk/python/mock/compare.html#mocking-内置的开放式上下文管理器

在@tbc0 answer上构建,以支持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())

最新更新