模拟测试用例将文件上传到S3

时间:2017-04-18 09:13:15

标签: python django unit-testing amazon-s3 mocking

我们如何模拟文件上传到S3。我试过这样的事情。

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
            })

但这实际上是上传到S3。我是新手。如何在不将文件上传到S3的情况下实现这一目标?

4 个答案:

答案 0 :(得分:1)

所以你的一般方法是正确的,但你需要覆盖boto的行为。所以你需要为它创建多个补丁。这样的事可能会奏效:

"""
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)

然后,您可以在函数中添加各种内容,作为预期的行为。希望这会有所帮助。

答案 1 :(得分:1)

以上解决方案有效。此外,我不得不模拟保存方法。

@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)

答案 2 :(得分:1)

经过大量研究,到目前为止,我发现的最简单的解决方案是使用setUp方法甚至是测试文件顶部的FileField修补猴子。

示例:

from django.core.files.storage import FileSystemStorage
from myapp.models import Report

class TestUploadS3(TestCase):

    def setUp(self):
        ...
        Report.pdf_file.field.storage = FileSystemStorage()
        ...

这样文件就不会上传到S3。

答案 3 :(得分:0)

根据上面的答案,我们可以使用补丁来确保我们在补丁模型中拥有正确的属性

    from unittest.mock import patch
    from django.core.files.storage import FileSystemStorage

    with patch('my_app.models.Mymodel.file_field.field.storage', FileSystemStorage()):
      ...test file behavior code

相关问题