Django:如何在测试视图时模拟文件上传

5

我想对我的视图进行单元测试。该视图应从表单中获取图像,将其上传到Amazon S3,最后显示上传的图像的预览。

我想要一个完整的示例来:

  1. 编写视图的单元测试。
  2. 在测试中模拟什么以及如何模拟以保持测试速度较快。
2个回答

7
视图可以使用RequestFactory进行测试。这样您就可以跳过所有中间件和URL解析,从而加快测试速度。请注意,您需要修改返回的request对象,以便所有装饰器都能正常处理视图函数。
在测试时,您可以为测试提供虚拟存储,以避免访问S3,并提供1x1像素的图像文件,以避免PIL抱怨它看起来不像图像文件(该文件可以在其他测试用例中重复使用,而不是通过编程方式创建)。或者,根据使用的客户端库,在进行实际模拟时,模拟所选库的存储对象的save()_save()方法(如果使用ImageFieldstorage参数,则为myapp.models,或者如果使用设置,则为Django内部)。
from django.test.client import RequestFactory
from django.test import TestCase

from myapp import views


class MyViewTest(TestCase):
    def setUp(self):
        self.rq = RequestFactory()

    def test_view(self):
        with open('test_data/test_img.png', 'rb') as img:
            req = self.rq.post('my_view_url', {'my_post': 'data', 'test': 1, 'image': img})
            resp = views.my_view(req)
            # ... asserts ...

嘿@kroolik,感谢你的回答。我是否可以不使用测试文件,也不完全访问数据库?我想使单元测试完全隔离。此外,你能否举个mocking的例子来扩展你的回答?这是最有趣的部分。 - Dmitry Wojciechowski
你可以模拟所有在视图中使用的模型的model.objectsmodel.save属性和方法,以避免访问数据库(请注意,某些视图装饰器仍可能使用数据库)。使用SimpleTestCase可以防止Django为该特定测试用例准备数据库。 - Maciej Gol

2
我不确定您是否可以在您的情境中使用,但SimpleUploadedFile帮助我在不触及数据库或文件系统的情况下测试上传视图。
如下所示,我在代码中硬编码了一个图像,用它来初始化SimpleUploadedFile对象。这样,SimpleUploadedFile实际上就像一个图像,因为它具有有效的二进制内容和有效的文件名。
# hex encoded bytes of a tiny valid png file
valid_png_hex = ['\x89', 'P', 'N', 'G', '\r', '\n', '\x1a', '\n', '\x00',
                 '\x00', '\x00', '\r', 'I', 'H', 'D', 'R', '\x00',
                 '\x00', '\x00', '\x01', '\x00', '\x00', '\x00', '\x01',
                 '\x08', '\x02', '\x00', '\x00', '\x00', '\x90',
                 'w', 'S', '\xde', '\x00', '\x00', '\x00', '\x06', 'b', 'K',
                 'G', 'D', '\x00', '\x00', '\x00', '\x00',
                 '\x00', '\x00', '\xf9', 'C', '\xbb', '\x7f', '\x00', '\x00',
                 '\x00', '\t', 'p', 'H', 'Y', 's', '\x00',
                 '\x00', '\x0e', '\xc3', '\x00', '\x00', '\x0e', '\xc3',
                 '\x01', '\xc7', 'o', '\xa8', 'd', '\x00', '\x00',
                 '\x00', '\x07', 't', 'I', 'M', 'E', '\x07', '\xe0', '\x05',
                 '\r', '\x08', '%', '/', '\xad', '+', 'Z',
                 '\x89', '\x00', '\x00', '\x00', '\x0c', 'I', 'D', 'A', 'T',
                 '\x08', '\xd7', 'c', '\xf8', '\xff', '\xff',
                 '?', '\x00', '\x05', '\xfe', '\x02', '\xfe', '\xdc', '\xcc',
                 'Y', '\xe7', '\x00', '\x00', '\x00', '\x00',
                 'I', 'E', 'N', 'D', '\xae', 'B', '`', '\x82']
valid_png_bin = "".join(valid_png_hex)
png = SimpleUploadedFile("tiny.png", valid_png_bin)
post_data = {u'image': [png], ...}

1
现在它使用字节:valid_png_bin = bytes("".join(valid_png_hex), "utf-8") - Karim N Gorjux

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接