Mock patching a callable upload_to in a Django ImageField

In Django I have a model and a test similar to the following, both in a photos module (Django app).

models.py

def get_user_photo_path(instance, filename):
    return str(uuid.uuid4())


class UserPhoto(models.Model):
    uploader = models.ForeignKey(User, on_delete=models.CASCADE)
    image = models.ImageField(upload_to=get_user_photo_path)
    upload_timestamp = models.DateTimeField(auto_now_add=True)

tests.py

    @mock.patch('photos.models.get_user_photo_path')
    def test_image_upload_path(self, mock_photo_path):
        mock_photo_path.return_value = 'mocktest'
        user_photo = UserPhoto.objects.create(
            uploader=self.parking_user, # these self variables are defined in setUp()
            image=self.image
        )
        expected_path = 'mocktest'
        self.assertTrue(user_photo.image.name.endswith(expected_path)) # Assertion fails

        # For demonstration, this assertion DOES pass
        from .models import get_user_photo_path
        self.assertEquals(get_user_photo_path(), 'mocktest')

This does not work, and I'm not sure why. But if I import the get_user_photo_path function directly in the test and call it, it does return 'mocktest'. I can only guess it has something to do with the way the ImageField processes its arguments, but from the source code nothing stands out to me as particularly strange or unusual.

I got around it by patching photos.models.uuid.uuid4 instead, but if someone could explain why the above patch didn't work, I would be very grateful!

Back to Top