How can I test a form with FileField in Django?
<p>I have this form:</p>

<pre><code># forms.py

class BookForm(forms.ModelForm):

    class Meta:
        model = Book
        fields = ['book_title', 'language', 'author', 'release_year', 'genre', 'ages', 'cover']
</code></pre>

<p><strong>Type of fields:</strong>
Where <code>book_title</code> and <code>author</code> are <code>CharField</code>, <code>language</code> and <code>genre</code> are too <code>CharField</code> but for them I have choice option, <code>release_year</code> and <code>ages</code> are <code>IntegerField</code>, and the last <code>cover</code> are <code>FileField</code>.</p>

<p><strong>Choice Options:</strong></p>

<pre><code># models.py
ENGLISH = 'english'
LANGUAGE_CHOICES = (
    (ENGLISH, 'English'),
)

ADVENTURE = 'adventure'
GENRE_CHOICES = (
    (ADVENTURE, 'Adventure'),
)
</code></pre>

<p><strong>Now:</strong> I want to test this form, but I don't know how can test <code>cover</code>, here is my form test.</p>

<pre><code># test_forms.py
from .. import forms
from django.core.files import File


class TestBookForm:
    def test_form(self):
        form = forms.BookForm(data={})
        assert form.is_valid() is False, 'Should be invalid if no data is given'

        img = File(open('background'))

        data = {'book_title': 'Lord Of The Rings',
                'language': 'english',
                'author': 'J. R. R. Tolkien',
                'release_year': 1957,
                'genre': 'adventure',
                'ages': 16,
                'cover': img}

        form = forms.BookForm(data=data)

        assert form.is_valid() is True
</code></pre>

<p><strong>I tried:</strong>
    from django.core.files.uploadedfile import SimpleUploadedFile</p>

<pre><code>img = open('background')
uploaded = SimpleUploadedFile(img.name, img.read())
{'cover': uploaded}
</code></pre>

<p><strong>This is my error:</strong></p>

<pre><code>E       assert False is True
E        +  where False = &lt;bound method BaseForm.is_valid of &lt;BookForm bound=True, valid=False, fields=(book_title;language;author;release_year;genre;ages;cover)&gt;&gt;()
E        +    where &lt;bound method BaseForm.is_valid of &lt;BookForm bound=True, valid=False, fields=(book_title;language;author;release_year;genre;ages;cover)&gt;&gt; = &lt;BookForm bound=True, valid=False, fields=(book_title;language;author;release_year;genre;ages;cover)&gt;
.is_valid
</code></pre>

<p><strong>NOTE:</strong> I use <code>Python 3.5</code>, <code>Django 1.9.4</code> and I start test using <code>py.test</code>.</p>

<p><strong>UPDATE:</strong> If i try <code>open('background.jpg')</code> don't work. <strong>Error:</strong> <code>FileNotFoundError: [Errno 2] No such file or directory: 'background.jpg'</code> <strong>I fix this</strong></p>

<p><strong>UPDATE 2:</strong> </p>

<p>I try to use <code>mock</code></p>

<pre><code>from django.core.files import File
import mock

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

{'cover': file_mock}
</code></pre>

<p>I try to use <code>InMemoryUploadedFile</code></p>

<pre><code>from io import BytesIO
from django.core.files.uploadedfile import InMemoryUploadedFile
from PIL import Image

im = Image.new(mode='RGB', size=(200, 200))  # create a new image using PIL
im_io = BytesIO()  # a StringIO object for saving image
im.save(im_io, 'JPEG')  # save the image to im_io
im_io.seek(0)  # seek to the beginning

image = InMemoryUploadedFile(
    im_io, None, 'random-name.jpg', 'image/jpeg', None, None
)

{'cover': image}
</code></pre>

<p>I fix the path to my image.</p>

<p><strong>I find the problem</strong> This is my code:</p>

<pre><code>#test_forms.py
from .. import forms
from django.core.files.uploadedfile import SimpleUploadedFile
import os

TEST_DIR = os.path.dirname(os.path.abspath(__file__))
TEST_DATA_DIR = os.path.join(TEST_DIR, 'data')


class TestBookForm:
    def test_form(self):
        form = forms.BookForm(data={})
        assert form.is_valid() is False, 'Should be invalid if no data is given'

        test_image_path = os.path.join(TEST_DATA_DIR, 'background.jpg')

        data = {'book_title': 'Lord Of The Rings',
                'language': 'english',
                'author': 'J. R. R. Tolkien',
                'release_year': 1957,
                'genre': 'adventure',
                'ages': 16}

        with open(test_image_path, 'rb') as f:
            form = forms.BookForm(data=data, files={'cover': SimpleUploadedFile('cover', f.read())})
            assert form.is_valid(), 'Invalid form, errors: {}'.format(form.errors)
</code></pre>

python django python-3.x django-forms django-testing