【问题标题】:Unable to return a tuple when mocking a function模拟函数时无法返回元组
【发布时间】:2015-07-17 14:10:39
【问题描述】:

我正在尝试熟悉 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。

我做错了什么,我该如何正确替换sanitize_line_endinginput_path.in_place() 的返回值。

【问题讨论】:

    标签: python unit-testing mocking


    【解决方案1】:

    经过多次挠头和参加聚会后,我终于遇到了这个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 提到的这不是上下文管理器。然而,我专注于让解包工作,在我能够实现之后,将元组替换为具有适当方法的构造。

    【讨论】:

      【解决方案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

      【讨论】:

        【解决方案3】:

        为了有效,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")
        

        【讨论】:

          【解决方案4】:

          试试这个从模拟函数返回元组:

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

          【讨论】:

          • type(mock_path).return_value = PropertyMock(return_value = (1, 2))
          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2012-07-19
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2017-10-01
          相关资源
          最近更新 更多