4

我有一个提供文件下载的视图的代码,它在浏览器中运行良好。现在我正在尝试使用内部 django Client.get 为它编写一个测试:

    response = self.client.get("/compile-book/", {'id': book.id})
    self.assertEqual(response.status_code, 200)
    self.assertEquals(response.get('Content-Disposition'), 
                      "attachment; filename=book.zip")

到目前为止,一切都很好。现在我想测试下载的文件是否是我希望下载的文件。所以我开始说:

    f = cStringIO.StringIO(response.content)

现在我的测试运行器响应:

Traceback (most recent call last):
  File ".../tests.py", line 154, in test_download
    f = cStringIO.StringIO(response.content)
  File "/home/epub/projects/epub-env/lib/python2.7/site-packages/django/http/response.py", line 282, in content
    self._consume_content()
  File "/home/epub/projects/epub-env/lib/python2.7/site-packages/django/http/response.py", line 278, in _consume_content
    self.content = b''.join(self.make_bytes(e) for e in self._container)   
  File "/home/epub/projects/epub-env/lib/python2.7/site-packages/django/http/response.py", line 278, in <genexpr>
    self.content = b''.join(self.make_bytes(e) for e in self._container)   
  File "/usr/lib/python2.7/wsgiref/util.py", line 30, in next 
    data = self.filelike.read(self.blksize) 
ValueError: I/O operation on closed file

即使我简单地这样做: self.assertIsNotNone(response.content) 我也会得到相同的 ValueError

在整个互联网(包括 django 文档)上,我能找到的关于测试下载的唯一主题是这个 stackoverflow 主题: Django Unit Test for testing a file download。尝试该解决方案导致了这些结果。对我来说,提出一个新问题已经足够古老和罕见了。

有人知道在 Django 中应该如何处理下载测试吗?(顺便说一句,在 python 2.7 上运行 django 1.5)

4

2 回答 2

6

这对我们有用。我们返回rest_framework.response.Response,但它也应该适用于常规的 Django 响应。

import io
response = self.client.get(download_url, {'id': archive_id})
downloaded_file = io.BytesIO(b"".join(response.streaming_content))

注意: streaming_content仅适用于StreamingHttpResponse(也 Django 1.10): https ://docs.djangoproject.com/en/1.10/ref/request-response/#django.http.StreamingHttpResponse.streaming_content

于 2016-09-23T07:51:12.677 回答
1

我有一些文件下载代码和一个与 Django 1.4 一起使用的相应测试。当我升级到 Django 1.5 时测试失败(与ValueError: I/O operation on closed file您遇到的错误相同)。

我通过将我的非测试代码更改为使用 aStreamingHttpResponse而不是标准来修复它HttpResponse。我使用了我的测试代码response.content,所以我首先迁移到CompatibleStreamingHttpResponse,然后将我的测试代码代码更改为使用response.streaming_content,以允许我放弃CompatibleStreamingHttpResponse支持StreamingHttpResponse.

于 2013-11-18T16:35:01.717 回答