Scenario:
from storages.backends.s3boto3 import S3Boto3Storage
class ImageStorage(S3Boto3Storage):
default_acl = "private"
bucket_name = settings.IMAGE_BUCKET_NAME
custom_domain = settings.IMAGE_CUSTOM_DOMAIN
querystring_auth = True
class Image(models.Model):
# snip...
image_file = models.ImageField(storage=ImageStorage())
Since I’m going to be reading from S3 and things will sometimes fail for various reasons, I’d like to be able to test my error handling in the view when I try to create a FileResponse
using that image_file
.
# views.py
def download_image(request, image_id):
# snip auth/permissions/etc checks
image = Image.objects.get(id=image_id)
try:
return http.FileResponse(image.image_file, filename=filename, as_attachment=True)
except IOError:
logger.exception(
"Failed to download photo %s from S3", image.id,
)
return http.ResponseNotFound('this is a temporary measure')
My question is: what do I need to mock to get the response handling to raise the IOError
?
Here’s a rough sample of what I’ve tried:
# tests.py
from unittest.mock import MagicMock, patch
from django.test import TestCase
from .models import Image
class ImageDownloadTestCase(TestCase):
def test_download_fails_read(self):
# snip image creation
mock_image = MagicMock()
mock_image.__iter__ = MagicMock(side_effect=IOError('foo')
with patch.object(Image.objects, 'get') as mock:
mock.return_value = mock_image
response = self.client.get('/path/to/download/1/')
self.assertEqual(response.status_code, 404)
I’ve tried both read
and __iter__
to no avail. What am I missing?