Python 3.8 中使用 Moto DynamoDB 和单元测试的拆卸问题

Teardown issue using Moto DynamoDB and unittest in Python 3.8

我正在尝试 运行 一些单元测试,使用 motounittest 基于来自 muhannad0 博客的 this example

下面是我的代码(缩小了 table 的创建,因为它不是那么重要)。

@mock_dynamodb2
class TestDatabaseFunctions(unittest.TestCase):

    def setUp(self):
        """
        Create database resource and mock table
        """
        print("Setting up")
        self.dynamodb = boto3.resource('dynamodb', region_name='eu-west-2')

        self.table = self.dynamodb.create_table(TableName='test-table', KeySchema=[{'AttributeName': 'pk', 'KeyType': 'HASH'}, {'AttributeName': 'sk','KeyType': 'RANGE'}], AttributeDefinitions=[{'AttributeName': 'pk', 'AttributeType': 'S'},{'AttributeName': 'sk', 'AttributeType': 'S'}], ProvisionedThroughput={'ReadCapacityUnits': 1, 'WriteCapacityUnits': 1})

        print("Waiting until the table exists")
        # Wait until the table exists.
        self.table.meta.client.get_waiter('table_exists').wait(TableName='test-table')
        assert self.table.table_status == 'ACTIVE'

        print("Ready to go")

    def tearDown(self):
        """
        Delete database resource and mock table
        """
        print("Tearing down")
        self.table.delete()
        self.dynamodb = None
        print("Teardown complete")

    def test_table_exists(self):
        """
        Test if our mock table is ready
        """
        print("Testing")
        self.assertIn('test-table', self.table.name)
        print("Test complete")


if __name__ == '__main__':
    unittest.main()

当我 运行 它时,我最终在 Python 3.8 的 mock.py 文件中遇到了一个错误。

=================================== FAILURES ===================================
___________________ TestDatabaseFunctions.test_table_exists ____________________
../../../env/lib/python3.8/site-packages/moto/core/models.py:102: in wrapper
    self.stop()
../../../env/lib/python3.8/site-packages/moto/core/models.py:86: in stop
    self.default_session_mock.stop()
../../../env/lib/python3.8/site-packages/mock/mock.py:1563: in stop
    return self.__exit__(None, None, None)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <mock.mock._patch object at 0x1128d2a30>, exc_info = (None, None, None)

    def __exit__(self, *exc_info):
        """Undo the patch."""
>       if self.is_local and self.temp_original is not DEFAULT:
E       AttributeError: '_patch' object has no attribute 'is_local'

../../../env/lib/python3.8/site-packages/mock/mock.py:1529: AttributeError

感谢我的穴居人调试,我可以说这个错误发生在 Teardown complete 消息之后,表明这是在测试成功执行后发生的,并且只在我的拆卸块完成后发生。

我非常喜欢 muhannad0 的这个例子,因为它使用了 class 装饰器,让我们可以轻松地在其中模拟 dynamodb,所以希望我们可以保留它。

如果您需要更多信息,请告诉我,您应该可以 运行 通过将代码复制并粘贴到您喜欢的 IDE 中并点击开始来自己 运行。

这看起来像是由于 moto 和模拟库之间的不兼容。此处正在讨论此问题:https://github.com/spulec/moto/issues/3535

临时解决方法是将这些库修复为兼容的版本。我目前正在将 mock 修复为 4.0.2 以避免 AttributeError:

pip install mock==4.0.2