unittestでFileFieldを持つDjangoモデルのインスタンスを作成する

ユニットテストでFileFieldを持つモデルのインスタンスを作成する場合どう書くべきか


こんなモデルがあるとして

class UploadFile(models.Model):
    file = models.FileField(upload_to='file')

思いつくまま書いてたらいくつかエラーを出したのでメモしておく

1のopenしたファイルをを渡すというのは完全な間違いだけど、2のエラー(SuspiciousOperation)は初めてみた

正しく動いたのは3のdjango.core.files.Fileのインスタンスを渡す、だけどテスト実行で実際にMEDIA_ROOT以下にファイルが作成されてしまう
これは削除しておきたいけど、他にもっといい方法がないだろうか

# coding=utf-8
from django.core.exceptions import SuspiciousOperation
from django.core.files import File
from django.test import TestCase
from apps.models import UploadFile


class UploadFileTest(TestCase):

    def test_ok(self):
        file_path = '/Users/yuhei/test.txt'

        # 1. openしたファイルをわたすのは間違い
        with self.assertRaises(AttributeError) as cm:
            self.instance = UploadFile.objects.create(file=open(file_path))
        self.assertEquals(cm.exception.message, "'file' object has no attribute '_committed'")


        # 2. パスを指定するとインスタンスを作成できるが読み出そうとするとエラーになる
        with self.assertRaises(SuspiciousOperation) as cm:
            self.instance = UploadFile.objects.create(file=file_path)
            file_contents = self.instance.file.read()
        self.assertEquals(cm.exception.message, "Attempted access to '/Users/yuhei/test.txt' denied.")


        # 3. from django.core.files import Fileのインスタンスとして渡す
        self.instance = UploadFile.objects.create(file=File(open(file_path)))
        file_contents = self.instance.file.read()

        # エラーにはならないが実際にMEDIA_ROOT以下にファイルが作成されるので削除する
        self.instance.file.delete()