2016-05-17 89 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

這對我有效,謝謝! :) –