Django testing model with ImageField

24,236

Solution 1

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')

Solution 2

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.

Solution 3

Tell the mock library to create a mock object based on Django's File class

import mock
from django.core.files import File

file_mock = mock.MagicMock(spec=File, name='FileMock')

and then use in your tests

newPhoto.image = file_mock

Solution 4

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')

Solution 5

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("RGB", 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())
Share:
24,236
Fabrizio A
Author by

Fabrizio A

Updated on July 08, 2022

Comments

  • Fabrizio A
    Fabrizio A almost 2 years

    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 PhotoTestCase(TestCase):
    
        def test_add_photo(self):
            newPhoto = Photo()
            newPhoto.image = # ??????
            newPhoto.save()
            self.assertEqual(Photo.objects.count(), 1)