在模拟函数时无法返回元组

时间:2015-07-17 14:10:40

标签: python unit-testing mocking

我正在尝试使用Python进行模拟,并且在尝试模拟以下函数时遇到了绊脚石。

helpers.py

from path import Path

def sanitize_line_ending(filename):
    """ Converts the line endings of the file to the line endings
        of the current system.
    """
    input_path = Path(filename)

    with input_path.in_place() as (reader, writer):
        for line in reader:
            writer.write(line)

test_helpers.py

@mock.patch('downloader.helpers.Path')
def test_sanitize_line_endings(self, mock_path):
    mock_path.in_place.return_value = (1,2)
    helpers.sanitize_line_ending('varun.txt')

但是我经常遇到以下错误:

ValueError: need more than 0 values to unpack

鉴于我已将返回值设置为元组,我不明白为什么Python无法解压缩。

然后我将代码更改为test_sanitize_line_endings存储打印返回值input_path.in_place(),我可以看到返回值是MagicMock对象。特别是它打印的东西 <MagicMock name='Path().in_place()' id='13023525345'> 如果我理解正确,我想要的是让mock_path成为具有返回元组的in_place函数的MagicMock。

我做错了什么,如何才能正确替换input_path.in_place()sanitize_line_ending的返回值。

4 个答案:

答案 0 :(得分:4)

经过多次讨论并参加聚会后,我终于遇到了blog post这终于解决了我的问题。

问题的症结在于我没有嘲笑正确的价值。由于我想要替换函数调用的结果,我需要编写的代码是:

@mock.patch('downloader.helpers.Path')
def test_sanitize_line_endings(self, mock_path):
    mock_path.return_value.in_place.return_value = (1,2)
    helpers.sanitize_line_ending('varun.txt')

这正确地导致函数能够解包元组,然后立即失败,因为像@ didi2002提到的那样这不是上下文管理器。然而,我专注于让解包工作,并且在我能够实现之后,使用适当的方法替换元组。

答案 1 :(得分:2)

我为这个错误ValueError: need more than 0 values to unpack而苦苦挣扎了几个小时。但是问题不在于我设置模型的方式(正确的方法由@ varun-madiath here描述)。

它在使用@mock.patch()装饰器:

@mock.patch('pika.BlockingConnection') @mock.patch('os.path.isfile') @mock.patch('subprocess.Popen') def test_foo(self, **mocked_connection**, mock_isfile, **mock_popen**):

必须颠倒参数的顺序!参见python docs

答案 2 :(得分:0)

要生效,input_path.in_place()的返回值必须是具有返回元组的__enter__方法的对象。

这是一个(非常详细)的例子:

def test():
    context = MagicMock()
    context.__enter__.return_value = (1, 2)

    func = MagicMock()
    func.in_place.return_value = context

    path_mock = MagicMock()
    path_mock.return_value = func

    with patch("path.Path", path_mock):
        sanitize_line_ending("test.txt")

答案 3 :(得分:0)

尝试此操作以从模拟函数返回元组:

ret = (1, 2)
type(mock_path).return_value = PropertyMock(return_value = ret)