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

Python Django:如何在测试视图时模拟文件上载,python,django,unit-testing,Python,Django,Unit Testing,我想对我的观点进行单元测试。视图应该从表单中获取图像,将它们上传到AmazonS3,最后显示上传图像的预览 我想请任何人举一个完整的例子: 如何为视图编写单元测试 如何在测试中模拟以及模拟什么以保持测试速度高 可以使用RequestFactory测试该视图。这样,您就可以跳过所有会降低测试速度的中间件和url解析。请注意,您必须修改返回的request对象,以便所有装饰视图函数的装饰器都可以使用它 在测试时,您可以为测试提供一个虚拟存储,这样S3就不会被命中,并提供一个1x1映像文件,这样PIL

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

我想请任何人举一个完整的例子:

  • 如何为视图编写单元测试
  • 如何在测试中模拟以及模拟什么以保持测试速度高

  • 可以使用
    RequestFactory
    测试该视图。这样,您就可以跳过所有会降低测试速度的中间件和url解析。请注意,您必须修改返回的
    request
    对象,以便所有装饰视图函数的装饰器都可以使用它

    在测试时,您可以为测试提供一个虚拟存储,这样S3就不会被命中,并提供一个1x1映像文件,这样
    PIL
    就不会尖叫,因为它看起来不像映像文件(该文件可以在其他测试用例中重用,而不是通过编程创建)。或者,根据使用的客户端库,在您进行实际模拟时模拟所选库的存储对象的
    save()
    \u save()
    方法(如果使用
    ImageField
    storage
    kwarg,可能是
    myapp.models
    ,如果使用设置,则模拟django内部)


    我不确定您是否可以在您的上下文中使用它,但帮助我在不接触数据库或文件系统的情况下测试上载视图

    正如您在下面看到的,我在代码中有一个硬编码图像,用于初始化
    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], ...}
    

    嘿@kroolik,谢谢你的回答。我是否可以不使用测试文件,也不点击数据库?我想让单元测试完全独立。你能用模拟的例子来扩展你的答案吗?这是最有趣的部分。您可以模拟视图中使用的模型的所有
    model.objects
    model.save
    属性和方法,以避免触及数据库(请注意,某些视图装饰程序可能仍然使用数据库)。使用
    SimpleTestCase
    可以防止django为该特定测试用例准备数据库。
    # 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], ...}