【问题标题】:Is there any way to mock file download in Python?有没有办法在 Python 中模拟文件下载?
【发布时间】:2017-01-22 17:07:21
【问题描述】:

我正在使用带有 Mock 的 Python 2.7。我有一个方法可以获取一个 url 并将其下载到一个临时文件中,然后根据业务逻辑规则重命名文件。我想测试这个重命名逻辑,但首先我必须模拟文件下载部分。这就是我卡住的地方。我在无限循环中使用urllib2.urlopen 及其read(chunkSize) 方法,检查read(chunkSize) 是否返回一些值。虽然这种方法在现实生活中有效,并且响应最终会被读取到 read(chunkSize) 不返回任何内容的末尾,但在模拟时我会得到一个无限循环。 read(chunkSize) 似乎总是有结果。读取响应内容后,如何让循环停止?这是我的代码:

import urllib2
from contextlib import closing
import unittest
import mock

def Method(url, temppath):
    chunkSize = 16 * 1024
    request = urllib2.Request(url)
    with closing(urllib2.urlopen(request, timeout = 5)) as response:
        with open(temppath, 'wb') as largeFile:
            while True:
                chunk = response.read(chunkSize)
                # print chunk # <- this will endlessly produce '0123456' when tested by test_Method in MyTestCase
                if not chunk:
                    break
                largeFile.write(chunk)
    # rename file from temppath to something new

class MyTestCase(unittest.TestCase):
    @mock.patch('urllib2.urlopen', autospec=True)
    @mock.patch('__main__.open', create=True)
    def test_Method(self, mock_open, mock_urlopen):
        mock_urlopen.return_value.read.return_value = b'0123456'
        Method('http://a.bcd/img.png', 'a:\\b\\1234567890.tmp')

if __name__ == '__main__':
    unittest.main()

【问题讨论】:

  • 您在问题中描述了两个不同的功能(下载和重命名);那么为什么您认为将这 两个 填充到一个方法中是合适的呢?换句话说:当您首先可以下载和单独的重命名方法时,将重命名部分的测试难度提高 5 倍有什么意义?那么你在测试重命名部分时就不需要模拟任何下载了!
  • @GhostCat 主要是因为我需要一种将文件下载到临时位置,根据规则重命名并返回结果文件名的方法。事实上,我确实有一个单独的方法来重命名文件,但我仍然需要一个调用下载和重命名方法的函数。

标签: python python-2.7 unit-testing download mocking


【解决方案1】:

分配一个列表值以返回side_effect attribute

mock_urlopen.return_value.read.side_effect = [b'0123456', b'']

模拟将遍历每个 read() 调用的值,因此最后一个返回空字节对象的调用将终止您的循环。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2023-02-07
    • 2020-09-12
    • 1970-01-01
    • 1970-01-01
    • 2011-07-24
    • 2011-02-23
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多