2016-05-17 120 views
3

我有一些python代码,它使用requests成功从URL下载图像,并将其保存到/tmp/中。我想测试这是否应该。我使用responses来测试抓取JSON文件,但我不知道如何模拟抓取文件的行为。使用Python请求和响应模拟下载文件

我认为这将会是类似嘲讽一个标准的响应,如下面的,但我想我消隐如何设置body是一个文件...

@responses.activate 
def test_download(): 
    responses.add(responses.GET, 'http://example.org/images/my_image.jpg', 
       body='', status=200, 
       content_type='image/jpeg') 
    #... 

UPDATE :继Ashafix的评论,我想这(蟒蛇3):

from io import BytesIO 

@responses.activate 
def test_download(): 
    with open('tests/images/tester.jpg', 'rb') as img1: 
     imgIO = BytesIO(img1.read()) 

    responses.add(responses.GET, 'http://example.org/images/my_image.jpg', 
       body=imgIO, status=200, 
       content_type='image/jpeg') 
    imgIO.seek(0) 
    #... 

但当随后,我测试的尝试做请求的代码我得到:

a bytes-like object is required, not '_io.BytesIO' 

感觉就像是几乎正确,但我很难过。

更新2:试图跟随史蒂夫·杰索普的建议:

@responses.activate 
def test_download(): 
    with open('tests/images/tester.jpg', 'rb') as img1: 
     responses.add(responses.GET, 'http://example.org/images/my_image.jpg', 
        body=img1.read(), status=200, 
        content_type='image/jpeg') 
     #... 

但此时代码正在测试提出了这一点:

I/O operation on closed file. 

当然图像仍然应该是with内开放块?

更新3:

r = requests.get(url, stream=True) 
if r.status_code == 200: 
    with open('/tmp/temp.jpg', 'wb') as f: 
     r.raw.decode_content = True 
     shutil.copyfileobj(r.raw, f) 

这似乎是最终shutil线正在生成:我测试的代码是这样的“关于关闭的文件I/O操作。”错误。我不明白这足够 - 文件的流 - 知道如何最好地嘲笑这种行为,测试下载的文件被保存到/tmp/

+0

这有帮助吗? http://stackoverflow.com/a/26364642/2776376 –

+0

'body = open(filename,'rb')。read()'不工作?在实践中,与任何“打开”调用一样,您可能希望将其用作上下文管理器。 –

+0

谢谢双方......我已经提出了两个建议,但尚未完成! –

回答

1

首先,总结一下我现在过长的问题...我测试一些代码,是这样的:

def download_file(url): 
    r = requests.get(url, stream=True) 
    if r.status_code == 200: 
     filename = os.path.basename(url) 
     with open('/tmp/%s' % filename, 'wb') as f: 
      r.raw.decode_content = True 
      shutil.copyfileobj(r.raw, f) 
     return filename 

它下载一个图像,流式传输,保存到/tmp/。我想嘲笑这个请求,所以我可以测试其他的东西。

@responses.activate 
def test_downloads_file(self): 
    url = 'http://example.org/test.jpg' 
    with open('tests/images/tester.jpg', 'rb') as img: 
     responses.add(responses.GET, url, 
         body=img.read(), status=200, 
         content_type='image/jpg', 
         adding_headers={'Transfer-Encoding': 'chunked'}) 
     filename = download_file(url) 
     # assert things here. 

有一次,我制定了使用open()这种方式,我仍然得到“关于关闭的文件I/O操作。”从shutil.copyfileobj()。停止这个事情是添加Transfer-Encoding标题,当我发出真正的请求时,标题中出现这个标题。

其他更好的解决方案的任何建议,非常欢迎!

+0

这工作了一下,现在不再有效;我仍然可以在关闭的文件上执行I/O操作。' –

+1

看起来像是用'requests' v2.12.0改变了这个结果。当安装v2.11.1时测试正常,但v2.12.0-v2.13.0不能正常运行。 –

2

您可能需要将stream=True传递给responses.add调用。例如:

@responses.activate 
def test_download(): 
    with open('tests/images/tester.jpg', 'rb') as img1: 
     responses.add(
      responses.GET, 'http://example.org/images/my_image.jpg', 
      body=img1.read(), status=200, 
      content_type='image/jpeg', 
      stream=True 
     ) 

似乎适用于我的情况。

+1

这对我有效,谢谢! :) –