【问题标题】:Django - how to write test for DRF ImageFieldDjango - 如何为 DRF ImageField 编写测试
【发布时间】:2019-05-26 22:32:05
【问题描述】:

我有以下序列化程序:

from rest_framework.serializers import Serializer, ImageField

class MySerializer(Serializer):
    avatar = ImageField()

如何为它编写单元测试? 我使用了 Django TestCase,但它引发了错误。

from django.test import TestCase

class MySerializerTest(TestCase):

    def setUp(self):
        self.data = {}
        ...

    def test_image(self):
        import tempfile
        self.data['avatar'] = tempfile.NamedTemporaryFile(suffix=".jpg").file
        r_data = json.dumps(self.data)
        j_data = json.loads(r_data)
        serializer = MySerializer(data=j_data)
        if not serializer.is_valid():
            import pprint
            pprint.pprint(serializer.errors)
        self.assertEqual(serializer.is_valid(), True)

但它会引发以下错误:

TypeError:“BufferedRandom”类型的对象不是 JSON 可序列化的

我的错误是什么?如何为图像字段编写测试?

【问题讨论】:

    标签: django django-rest-framework django-tests django-unittest


    【解决方案1】:

    我建议使用 django 中的 SimpleUploadedFile 类并使用 Pillow 包创建和映像。请参阅下面的示例。

    from PIL import Image
    
    from django.core.files.uploadedfile import SimpleUploadedFile
    from django.test import TestCase
    from django.utils.six import BytesIO
    
    
    class MySerializerTest(TestCase):
        ...
    
        def test_image(self):
            image = BytesIO()
            Image.new('RGB', (100, 100)).save(image, 'JPEG')
            image.seek(0)
    
            self.data['avatar'] = SimpleUploadedFile('image.jpg', image.getvalue())
            serializer = MySerializer(data=self.data)
            self.assertEqual(serializer.is_valid(), True)
    

    【讨论】:

    • 它再次引发错误。 “TypeError:‘SimpleUploadedFile’类型的对象不是 JSON 可序列化的”
    • 不要序列化成JSON,为什么需要呢?
    • 那么,我如何测试包含 ImageField 的序列化程序?如您所见,它是一个带有 ImageField 的序列化程序。我想为它写测试。
    • 如您所见,它已经写在我的示例中。您不需要将 JSON 字符串传递给 Serializer,简单的字典就足以使其工作。
    • 现在它引发了另一个错误!错误是“'str' 对象不可序列化”。此错误在“serializer.is_valid()”行中。
    【解决方案2】:

    通常当您上传文件时,您会使用multipart 请求格式,视图会将图像转换为InMemoryUploadedFile 对象,然后传递到您的序列化程序中

    因此,为了修复您的测试,我建议您尝试:

    from PIL import Image
    from tempfile import NamedTemporaryFile
    from django.conf.files.uploadedfile import InMemoryUploadedFile
    
    ...
    
    def test_image(self):
        image = Image.new("RGB", (100, 100))
        with NamedTemporaryFile(suffix=".png", mode="w+b") as tmp_file:
            image.save(tmp_file, format="png")
            tmp_file.seek(0)
            byio = BytesIO(temp_file.read())
            inm_file = InMemoryUploadedFile(
                file=byio,
                field_name="avatar",
                name="testImage.png",
                content_type="image/png",
                size=byio.getbuffer().nbytes,
                charset=None,
            )
    
            self.data['avatar'] = inm_file
            serializer = MySerializer(data=self.data)
            if not serializer.is_valid():
                import pprint
                pprint.pprint(serializer.errors)
            self.assertEqual(serializer.is_valid(), True)
    

    这是做什么的:

    1. 使用 PIL.Image 在内存中创建图像
    2. 创建一个 NamedTemporaryFile 来存储图像数据
    3. 获取 NamedTemporaryFile 并读入 InMemoryUploadedFile
    4. 将此 InMemoryUploadedFile 传递到序列化程序中

    【讨论】:

    • 它会引发错误:“TypeError: 需要一个类似字节的对象,而不是 'InMemoryUploadedFile'”
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-10-23
    • 1970-01-01
    • 2018-05-10
    • 1970-01-01
    • 2014-09-14
    • 1970-01-01
    相关资源
    最近更新 更多