Django testing model with ImageField

后端 未结 8 1639
爱一瞬间的悲伤
爱一瞬间的悲伤 2020-12-07 16:52

I need to test the Photo model of my Django application. How can I mock the ImageField with a test image file?

tests.py

class PhotoT         


        
相关标签:
8条回答
  • 2020-12-07 16:58

    My approach how to test model with no intention to pass any useful data:

    from django.core.files import File
    SomeModel.objects.create(image=File(file=b""))
    
    0 讨论(0)
  • 2020-12-07 16:59

    Solution:

    from StringIO import StringIO
    # in python 3: from io import StringIO
    from PIL import Image
    from django.core.files.base import File
    

    And create a static method in your TestCase class:

    @staticmethod
    def get_image_file(name='test.png', ext='png', size=(50, 50), color=(256, 0, 0)):
        file_obj = StringIO()
        image = Image.new("RGBA", size=size, color=color)
        image.save(file_obj, ext)
        file_obj.seek(0)
        return File(file_obj, name=name)
    

    Example:

    instance = YourModel(name=value, image=self.get_image_file())
    
    0 讨论(0)
  • 2020-12-07 17:01

    If you don't want to create an actual file in the filesystem, you can use this 37-byte GIF instead, small enough to a be a bytes literal in your code:

    from django.core.files.uploadedfile import SimpleUploadedFile
    
    small_gif = (
        b'\x47\x49\x46\x38\x39\x61\x01\x00\x01\x00\x00\x00\x00\x21\xf9\x04'
        b'\x01\x0a\x00\x01\x00\x2c\x00\x00\x00\x00\x01\x00\x01\x00\x00\x02'
        b'\x02\x4c\x01\x00\x3b'
    )
    uploaded = SimpleUploadedFile('small.gif', small_gif, content_type='image/gif')
    
    0 讨论(0)
  • 2020-12-07 17:10

    For future users, I've solved the problem. You can mock an ImageField with a SimpleUploadedFile instance.

    test.py

    from django.core.files.uploadedfile import SimpleUploadedFile
    
    newPhoto.image = SimpleUploadedFile(name='test_image.jpg', content=open(image_path, 'rb').read(), content_type='image/jpeg')
    
    0 讨论(0)
  • 2020-12-07 17:11

    You can do a few additional things to (1) avoid having to keep a dedicated test image around, and (2) ensure that all test files created during testing are deleted right after:

    import shutil
    import tempfile
    
    from django.core.files.uploadedfile import SimpleUploadedFile
    from django.test import TestCase, override_settings
    
    MEDIA_ROOT = tempfile.mkdtemp()
    
    @override_settings(MEDIA_ROOT=MEDIA_ROOT)
    class MyTest(TestCase):
    
        @classmethod
        def tearDownClass(cls):
            shutil.rmtree(MEDIA_ROOT, ignore_errors=True)  # delete the temp dir
            super().tearDownClass()
    
        def test(self):
            img = SimpleUploadedFile('test.jpg', b'whatevercontentsyouwant')
            # ^-- this will be saved in MEDIA_ROOT
            # do whatever ...
    
    0 讨论(0)
  • 2020-12-07 17:16

    You can use a temporary file, using tempfile. So you don't need a real file to do your tests.

    import tempfile
    
    image = tempfile.NamedTemporaryFile(suffix=".jpg").name
    

    If you prefer to do manual clean-up, use tempfile.mkstemp() instead.

    0 讨论(0)
提交回复
热议问题