Django - 如何为 DRF ImageField 编写测试

Django - how to write test for DRF ImageField

我有以下序列化程序:

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: Object of type 'BufferedRandom' is not JSON serializable

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

通常当您上传文件时,您会使用 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. 在内存中创建图像
  3. 创建一个 NamedTemporaryFile 来存储图像数据
  4. 获取 NamedTemporaryFile 并读入 InMemoryUploadedFile
  5. 将此 InMemoryUploadedFile 传递到序列化程序

我建议使用 django 中的 SimpleUploadedFile class 并使用 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)