如何用unittest.mock测试下面的代码:

def testme(filepath):
    with open(filepath) as f:
        return f.read()

当前回答

要将mock_open用于一个简单的文件read()(本页上已经给出的原始mock_open片段更适合于write):

my_text = "some text to return when read() is called on the file object"
mocked_open_function = mock.mock_open(read_data=my_text)

with mock.patch("__builtin__.open", mocked_open_function):
    with open("any_string") as f:
        print f.read()

注意,根据mock_open的文档,这是专门针对read()的,所以不会适用于常见的模式,例如for line in f。

使用python 2.6.6 / mock 1.0.1

其他回答

Python 3

补丁内置命令。打开并使用mock_open,它是模拟框架的一部分。用作上下文管理器的Patch返回用于替换补丁的对象:

from unittest.mock import patch, mock_open
with patch("builtins.open", mock_open(read_data="data")) as mock_file:
    assert open("path/to/open").read() == "data"
mock_file.assert_called_with("path/to/open")

如果您想使用patch作为装饰器,那么使用mock_open()的结果作为patch的new=参数可能会有点奇怪。相反,使用patch的new_callable=参数,并记住patch不使用的每个额外参数将被传递给new_callable函数,如补丁文档中所述:

Patch()接受任意关键字参数。这些将在构造时传递给Mock(或new_callable)。

@patch("builtins.open", new_callable=mock_open, read_data="data")
def test_patch(mock_file):
    assert open("path/to/open").read() == "data"
    mock_file.assert_called_with("path/to/open")

记住,在这种情况下,patch将模拟对象作为参数传递给测试函数。

Python 2

你需要修补__builtin__。打开而不是内置。Open和mock不是unittest的一部分,你需要分别安装和导入它:

from mock import patch, mock_open
with patch("__builtin__.open", mock_open(read_data="data")) as mock_file:
    assert open("path/to/open").read() == "data"
mock_file.assert_called_with("path/to/open")

这样做的方式在mock 0.7.0中已经改变,它最终支持模拟python协议方法(magic方法),特别是使用MagicMock:

http://www.voidspace.org.uk/python/mock/magicmock.html

一个作为上下文管理器打开的mock示例(来自mock文档中的示例页面):

>>> open_name = '%s.open' % __name__
>>> with patch(open_name, create=True) as mock_open:
...     mock_open.return_value = MagicMock(spec=file)
...
...     with open('/some/path', 'w') as f:
...         f.write('something')
...
<mock.Mock object at 0x...>
>>> file_handle = mock_open.return_value.__enter__.return_value
>>> file_handle.write.assert_called_with('something')

来自github代码片段,用于修补python中的读写功能。

源代码链接在这里

import configparser
import pytest

simpleconfig = """[section]\nkey = value\n\n"""

def test_monkeypatch_open_read(mockopen):
    filename = 'somefile.txt'
    mockopen.write(filename, simpleconfig)
 
    parser = configparser.ConfigParser()
    parser.read(filename)
    assert parser.sections() == ['section']
 
def test_monkeypatch_open_write(mockopen):
    parser = configparser.ConfigParser()
    parser.add_section('section')
    parser.set('section', 'key', 'value')
 
    filename = 'somefile.txt'
    parser.write(open(filename, 'wb'))
    assert mockopen.read(filename) == simpleconfig

要将mock_open用于一个简单的文件read()(本页上已经给出的原始mock_open片段更适合于write):

my_text = "some text to return when read() is called on the file object"
mocked_open_function = mock.mock_open(read_data=my_text)

with mock.patch("__builtin__.open", mocked_open_function):
    with open("any_string") as f:
        print f.read()

注意,根据mock_open的文档,这是专门针对read()的,所以不会适用于常见的模式,例如for line in f。

使用python 2.6.6 / mock 1.0.1

如果你不需要进一步的文件,你可以装饰测试方法:

@patch('builtins.open', mock_open(read_data="data"))
def test_testme():
    result = testeme()
    assert result == "data"