Django testing model with ImageField

Each Answer to this Q is separated by one/two green lines.

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

class PhotoTestCase(TestCase):

    def test_add_photo(self):
        newPhoto = Photo()
        newPhoto.image = # ??????
        self.assertEqual(Photo.objects.count(), 1)

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

from django.core.files.uploadedfile import SimpleUploadedFile

newPhoto.image = SimpleUploadedFile(name="test_image.jpg", content=open(image_path, 'rb').read(), content_type="image/jpeg")

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.

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

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 = (
uploaded = SimpleUploadedFile('small.gif', small_gif, content_type="image/gif")


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:

def get_image_file(name="test.png", ext="png", size=(50, 50), color=(256, 0, 0)):
    file_obj = StringIO()
    image ="RGB", size=size, color=color), ext)
    return File(file_obj, name=name)


instance = YourModel(name=value, image=self.get_image_file())

For someone to try upload-image test with python 3.xx

I fix little with Maxim Panfilov’s excellent answer to make more dummy image with independent name.

from io import BytesIO
from PIL import Image
from django.core.files.base import File

#in your TestCase class:
class TestClass(TestCase):
    def get_image_file(name, ext="png", size=(50, 50), color=(256, 0, 0)):
        file_obj = BytesIO()
        image ="RGBA", size=size, color=color), ext)
        return File(file_obj, name=name)

    def test_upload_image(self):
        c= APIClient()
        image1 = self.get_image('image.png')
        image2 = self.get_image('image2.png')
        data = 
                "image1": iamge1,
                "image2": image2,
        response ='/api_address/', data ) 
        self.assertEqual(response.status_code, 201) 

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

class MyTest(TestCase):

    def tearDownClass(cls):
        shutil.rmtree(MEDIA_ROOT, ignore_errors=True)  # delete the temp dir

    def test(self):
        img = SimpleUploadedFile('test.jpg', b'whatevercontentsyouwant')
        # ^-- this will be saved in MEDIA_ROOT
        # do whatever ...

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

from django.core.files import File

If you use Factory Boy to generate your test data, that library handles this situation with an ImageField factory.

Here is a complete example. I’m assuming that all of these files are in the same Django app. example:

from django.db import models

class YourModel(models.Model):
    image = models.ImageField(upload_to="files/") example:

import factory
from . import models

class YourModelFactory(factory.django.DjangoModelFactory):
    class Meta:
        model = models.YourModel
    image = factory.Django.ImageField() example:

from django import test    
from . import factories

class YourModelTests(test.TestCase):
    def test_image_model(self):
        yourmodel = factories.YourModelFactory()

The answers/resolutions are collected from stackoverflow, are licensed under cc by-sa 2.5 , cc by-sa 3.0 and cc by-sa 4.0 .