How can we mock file upload to S3. I tried something like this.
file_mock = mock.MagicMock(spec=File, name='FileMock')
@mock.patch('storages.backends.s3boto.S3BotoStorage', FileSystemStorage)
def test_post_file(self):
response = self.client.post('/api/v1/file_upload/', {
"status": "NEW",
"amount": "250.00",
"bill": file_mock
})
But this is in inturn actually uploading to S3. I'm new to this. How can this be implemented without uploading files to S3?
So your general approach is correct but you need to override the behavior of boto. So you need to create multiple patches for it. Something like this would probably work:
"""
Mock Connection class for Bucket
"""
class MockConnection():
def __init__(self):
self.provider = 'AWS'
def delete_key(self, param):
pass
"""
Mock Connection class which is called for connecting to s3
"""
class MockS3Connection():
def get_bucket(self, name, validate=False):
return Bucket(MockConnection(), 'bucket')
"""
Mock Key class which also gets the bucket
"""
class MockKey():
def __init__(self, bucket):
self.bucket = bucket
def set_contents_from_string(self, data, headers):
pass
def set_acl(self, read):
pass
"""
Mock the function which connects to S3
"""
def mock_connect_s3():
return MockS3Connection()
class TestUploadResource(BaseResourceTestCase):
"""
Test Document upload
"""
def setUp(self):
super(TestUploadResource, self).setUp()
@mock.patch('boto.connect_s3', new = mock_connect_s3)
@mock.patch("boto.s3.key.Key", MockKey)
def test_file_is_accepted(self):
'''
Test case to check whether file is uploaded
'''
name = raw_input('Document1')+'.pdf'
file = open(name,'rw') # Trying to create a new file or open one
"""
Call the upload docs command with the file which
we want to save
"""
response = self.client.post('some-url')
"""
Check whether the file is going and the response of creation
is coming or not
"""
self.assertEqual(201, response.status_code)
You can then add various things in your function as what would be the expected behavior. Hope this helps.
The above solution worked. Also i had to mock the save method.
@mock.patch.object(<Model>, 'save')
@mock.patch('boto.connect_s3', new=mock_connect_s3)
@mock.patch("boto.s3.key.Key", MockKey)
def test_post_file(self, save_mock):
response = self.client.post('/api/v1/file_upload/', {
"status": "NEW",
"amount": "250.00",
"bill": file_mock
})
self.assertTrue(save_mock.called)
self.assertEqual(201, response.status_code)
After a lot of research, the simplest solution I have found so far is monkey patching the FileField in the setUp method or even at the top of the tests files.
Example:
from django.core.files.storage import FileSystemStorage
from myapp.models import Report
class TestUploadS3(TestCase):
def setUp(self):
...
Report.pdf_file.field.storage = FileSystemStorage()
...
This way the file is not uploaded to S3.