有没有办法在Python中模拟文件下载?

时间:2017-01-22 17:07:22

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

我使用Python 2.7和Mock。我有一个方法,它接受一个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()

1 个答案:

答案 0 :(得分:4)

指定值的列表以返回side_effect attribute

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

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