Python:用于测试功能的模拟文件输入

use*_*518 5 unit-testing mocking python-3.x

我知道有类似的帖子,但我没有找到类似的帖子。

我在 python 中有一个函数,它接收要读取和处理的文件名作为输入并返回一些东西,我想测试我的函数的输出是否。例子:

#main function
def myfunction(filename):
    f=open(filename)

    for line in f:
        # process data
        pass
    f.close()

    return # something

#test function for the main function
def test_myfunction():
    mockfile = #mymockfile
    assert myfunction(mockfile) == #something
Run Code Online (Sandbox Code Playgroud)

我怎样才能创建一个模拟文件来测试这个函数而不必编写一个读取文件?

这是我发现的最接近模拟我需要的东西(http://www.voidspace.org.uk/python/mock/helpers.html#mock-open

Opp*_*ppy 5

由于遇到了同样的问题,请在下面找到我的答案。

2022 年 12 月更新

我找到了一个比 2018 年的原始解决方案更简单的解决方案。使用 Python 3.9.2 并使用 pytest 从命令行运行脚本:

import unittest.mock 

#main function
def myfunction(filename):
    f=open(filename)
    maximum = 0
    for line in f:
        if maximum < len(line):
            maximum = len(line)
        pass
    f.close()
    return maximum


def test_myfunction():
    mock_file = unittest.mock.mock_open(read_data=('12characters\n13_characters'))
    with unittest.mock.patch('builtins.open', mock_file):
        actual_result = myfunction('foo')
    assert not actual_result == 12
    assert actual_result == 13

Run Code Online (Sandbox Code Playgroud)

原答案2018

我通过 Eclipse 中的 pydev 插件使用了 Python 3.6 和 Py.test。

import unittest.mock as mock
from unittest.mock import mock_open

#main function
def myfunction(filename):
    f=open(filename)
    maximum = 0
    for line in f:
        if maximum < len(line):
            maximum = len(line)
        pass
    f.close()
    return maximum

#test function for the main function
@mock.patch('builtins.open', new_callable=mock_open, create=True)
def test_myfunction(mock_open):
    mock_open.return_value.__enter__ = mock_open
    mock_open.return_value.__iter__ = mock.Mock(
        return_value = iter(['12characters', '13_characters']))
    answer = myfunction('foo')
    assert not answer == 12
    assert answer == 13
Run Code Online (Sandbox Code Playgroud)