12

我正在使用 moto 和 Python 3.7 来模拟一些 S3 交互。如果所有模拟代码都包含在测试方法中,那么 moto 似乎可以正常工作。当我将一些初步代码移至setUp()时,测试失败,就好像setUp()从未运行过一样。

import unittest

import boto3
from moto import mock_s3

class BucketFacadeTests(unittest.TestCase):

    @mock_s3
    def setUp(self):
        print('setUp called')
        s3 = boto3.resource('s3', region_name='us-east-1')
        s3.create_bucket(Bucket='bucket')
        key = 'a/b/c/d.txt'
        object = s3.Object('bucket', key)
        object.put(Body='my dog has fleas')

    def do_test(self):
        s3 = boto3.resource('s3', region_name='us-east-1')
        the_object = s3.Object('bucket', 'a/b/c/d.txt')
        string_data = the_object.get()['Body'].read().decode('utf-8')
        self.assertEqual('my dog has fleas', string_data)

    @mock_s3
    def test_bucket_can_be_accessed_with_setup(self):
        self.do_test()

    @mock_s3
    def test_bucket_can_be_accessed_without_setup(self):
        # This does what setUp() should
        s3 = boto3.resource('s3', region_name='us-east-1')
        s3.create_bucket(Bucket='bucket')
        key = 'a/b/c/d.txt'
        object = s3.Object('bucket', key)
        object.put(Body='my dog has fleas')

        self.do_test()

当我不依赖时setUp(),一切都按预期运行

Testing started at 07:49 ...
/Users/paul/.virtualenvs/nui-converter/bin/python "/Applications/PyCharm CE.app/Contents/helpers/pycharm/_jb_unittest_runner.py" --target BucketFacade2Tests.BucketFacadeTests.test_bucket_can_be_accessed_without_setup
Launching unittests with arguments python -m unittest BucketFacade2Tests.BucketFacadeTests.test_bucket_can_be_accessed_without_setup in /Users/Paul/as/nui-converter/tests/InventoryLoader
setUp called


Ran 1 test in 0.103s

OK

Process finished with exit code 0

然而,当我依赖时它失败了setUp()

Testing started at 07:56 ...
/Users/paul/.virtualenvs/nui-converter/bin/python "/Applications/PyCharm CE.app/Contents/helpers/pycharm/_jb_unittest_runner.py" --target BucketFacade2Tests.BucketFacadeTests.test_bucket_can_be_accessed_with_setup
Launching unittests with arguments python -m unittest BucketFacade2Tests.BucketFacadeTests.test_bucket_can_be_accessed_with_setup in /Users/Paul/as/nui-converter/tests/InventoryLoader
setUp called


Ran 1 test in 0.183s

FAILED (errors=1)

Error
Traceback (most recent call last):
  File "/usr/local/Cellar/python/3.7.1/Frameworks/Python.framework/Versions/3.7/lib/python3.7/unittest/case.py", line 59, in testPartExecutor
    yield
  File "/usr/local/Cellar/python/3.7.1/Frameworks/Python.framework/Versions/3.7/lib/python3.7/unittest/case.py", line 615, in run
    testMethod()
  File "/Users/paul/.virtualenvs/nui-converter/lib/python3.7/site-packages/moto/core/models.py", line 74, in wrapper
    result = func(*args, **kwargs)
  File "/Users/Paul/as/nui-converter/tests/InventoryLoader/BucketFacade2Tests.py", line 27, in test_bucket_can_be_accessed_with_setup
    self.do_test()
  File "/Users/Paul/as/nui-converter/tests/InventoryLoader/BucketFacade2Tests.py", line 22, in do_test
    string_data = the_object.get()['Body'].read().decode('utf-8')
  File "/Users/paul/.virtualenvs/nui-converter/lib/python3.7/site-packages/boto3/resources/factory.py", line 520, in do_action
    response = action(self, *args, **kwargs)
  File "/Users/paul/.virtualenvs/nui-converter/lib/python3.7/site-packages/boto3/resources/action.py", line 83, in __call__
    response = getattr(parent.meta.client, operation_name)(**params)
  File "/Users/paul/.virtualenvs/nui-converter/lib/python3.7/site-packages/botocore/client.py", line 357, in _api_call
    return self._make_api_call(operation_name, kwargs)
  File "/Users/paul/.virtualenvs/nui-converter/lib/python3.7/site-packages/botocore/client.py", line 661, in _make_api_call
    raise error_class(parsed_response, operation_name)
botocore.errorfactory.NoSuchBucket: An error occurred (NoSuchBucket) when calling the GetObject operation: The specified bucket does not exist


Process finished with exit code 1

我是在做错什么还是将 moto 推到了极限?

4

1 回答 1

15

问题是您将 mock_s3 装饰器直接应用于setUp()方法test methods。这导致了单独的模拟 s3 环境,因此不共享该setUp()方法中所做的任何事情。

解决方案是将@mock_s3装饰器应用于整个BucketFacadeTests类。

下面的代码应该按预期工作。

import unittest

import boto3
from moto import mock_s3

@mock_s3
class BucketFacadeTests(unittest.TestCase):


    def setUp(self):
        print('setUp called')
        s3 = boto3.resource('s3', region_name='us-east-1')
        s3.create_bucket(Bucket='bucket')
        key = 'a/b/c/d.txt'
        object = s3.Object('bucket', key)
        object.put(Body='my dog has fleas')

    def do_test(self):
        s3 = boto3.resource('s3', region_name='us-east-1')
        the_object = s3.Object('bucket', 'a/b/c/d.txt')
        string_data = the_object.get()['Body'].read().decode('utf-8')
        self.assertEqual('my dog has fleas', string_data)

    def test_bucket_can_be_accessed_with_setup(self):
        self.do_test()

    def test_bucket_can_be_accessed_without_setup(self):
        # This does what setUp() should
        s3 = boto3.resource('s3', region_name='us-east-1')
        s3.create_bucket(Bucket='bucket')
        key = 'a/b/c/d.txt'
        object = s3.Object('bucket', key)
        object.put(Body='my dog has fleas')

        self.do_test()
于 2019-04-24T07:31:57.237 回答