5

I'm a testing noob and I'm trying to figure out how to write a test to confirm that a model form is valid and will generate a new instance of Post, which is a model that has an image field.

I looked some other SO posts, and it looks like I should be using SimpleUploadedFile to mock the image field. I'm having a hard time understanding how SimpleUploadedFile works (haven't found any straightforward documentation for this application), and different SO posts use some different looking syntax.

Am I supposed to point to a real file path to an actual image that is held somewhere in my Django app, or does this create a fake file to be used?

tests.py

class CreatePost(TestCase):
    def test_create_post(self):
        data = {
            "content": "This is a post, I'm testing it out"
        }
        files_data = {
            "image": SimpleUploadedFile(name='test_image.jpg', content=open(image_path, 'rb').read(), content_type='image/jpeg') 
        }
        response = self.client.post("/new", data=data, files=files_data)
        self.assertEqual(Post.objects.count(),1)
        self.assertRedirects(response, 'index')

models.py

class Post(models.Model):
    content = models.CharField(max_length=260)
    timestamp = models.DateTimeField(auto_now_add=True)
    posted_by = models.ForeignKey(User, on_delete=models.CASCADE, related_name="posts")
    liked_by = models.ManyToManyField(User, blank=True, related_name="liked_posts")
    image = models.ImageField(upload_to='uploads/', verbose_name='image')
    def __str__(self):
        return f"{self.posted_by} posted {self.content} at {self.timestamp}"
    def is_valid_post(self):
        return len(self.content) <= 260 and len(self.content) >= 0
     

class Post_form(ModelForm):
    class Meta: 
        model = Post
        fields = ['content', 'image']
user12457151
  • 853
  • 2
  • 12
  • 25

1 Answers1

6

I'm having a hard time understanding how SimpleUploadedFile works (haven't found any straightforward documentation for this application)

Take a look on source code of SimpleUploadedFile — it's a simple representation of a file, which just has content, size, and a name.

You don't need to point to a real file of real image (unless you want to). So you can replace real image (in your example — open(image_path, 'rb').read()) with fake data or even empty binary data b''

Also put all request fields under single data object.

And I don't find initialisation of client in your example.

Summarise, your test will finally look like on this one:

from django.test import Client, TestCase

class CreatePost(TestCase):
    def setUp(self):
        self.client = Client()

    def test_create_post(self):
        data = {
            "content": "This is a post, I'm testing it out",
            "image": SimpleUploadedFile(name='test_image.jpg', content=b'', content_type='image/jpeg')
        }
        response = self.client.post("/new", data=data)

        self.assertEqual(Post.objects.count(),1)
        self.assertRedirects(response, 'index')
ujlbu4
  • 1,058
  • 8
  • 8