【问题标题】:How to mock multiple dynamodb tables using moto如何使用 moto 模拟多个 dynamodb 表
【发布时间】:2022-01-17 11:25:01
【问题描述】:

我有一个使用 3 个 dynamodb 表的函数 create。如何模拟三个 Dynamo 数据库表?

def create():
    //This function uses a dynamodb table "x"
    // Then it calls my_table() function

def my_table():
    // This function basically uses two dynamodb table "y" and "z"
    // This function returns a value which is used in create() function.

我的测试文件有以下代码 -

@patch.dict(os.environ, {"DYNAMODB_TABLE": "x",
'second_TABLE': "y",
'Third_TABLE': "z"
})
def test_create():

    dynamodb_test()
    event = {  // my event values}

    result = create(event)
    assert result == 200




def dynamodb_test():

    with mock_dynamodb2():
        dynamodb = boto3.client('dynamodb', region_name='us-east-1')
        dynamodb.create_table(
            TableName=os.environ["DYNAMODB_TABLE"],
            KeySchema=[
                {
                'AttributeName': 'id',
                'KeyType': 'HASH'
                }
            ],
            AttributeDefinitions=[
                {
                'AttributeName': 'id',
                'AttributeType': 'S'
                }
            ],
            ProvisionedThroughput={
            'ReadCapacityUnits': 1,
            'WriteCapacityUnits': 1
            }
        )
        yield dynamodb

每当我使用 pytest 测试 test_create() 函数时,我都会得到

botocore.exceptions.ClientError: 发生错误 (ExpiredTokenException) 时 调用扫描操作:请求中包含的安全令牌已过期

我认为它试图访问实际的 aws dynamo db,但我希望它使用模拟 dynamodb。我怎样才能做到这一点?

【问题讨论】:

    标签: amazon-web-services amazon-dynamodb moto


    【解决方案1】:

    Moto 仅在满足两个条件时才起作用:

    • 要测试的逻辑在 Moto 上下文中执行
    • 在创建任何 boto3 客户端(或资源)之前启动 Moto 上下文

    您示例中的 Moto 上下文 with mock_dynamodb2() 已本地化为 dynamodb_test 函数。函数完成后,mock 不再活跃,Boto3 确实会尝试访问 AWS 本身。

    解决方案

    以下测试函数将满足这两个条件:

    @patch.dict(os.environ, {"DYNAMODB_TABLE": "x",
    'second_TABLE': "y",
    'Third_TABLE': "z"
    })
    # Initialize the mock here, so that it is effective for the entire test duration
    @mock_dynamodb2
    def test_create():
    
        dynamodb_test()
        event = {  // my event values}
    
        # Ensure that any boto3-clients/resources created in the logic are initialized while the mock is active
        from ... import create
    
        result = create(event)
        assert result == 200
    
    def dynamodb_test():
    
        # There is no need to start the mock-context again here, so create the table immediately
        dynamodb = boto3.client('dynamodb', region_name='us-east-1')
        dynamodb.create_table(...)
    
    

    您提供的测试代码没有讨论创建表 yz - 如果逻辑期望它们存在,您当然也必须手动创建它们(就像表 x 是创建于dynamodb_test


    可以在此处找到有关导入怪癖的文档:http://docs.getmoto.org/en/latest/docs/getting_started.html#recommended-usage

    【讨论】:

    • 谢谢伯特,这就是我想知道的。
    【解决方案2】:

    我相信this post 与您的几乎相同。你可以试试这个或利用其他一些现有的工具,如localstackdynamodb-local。 localstack 的 Python 客户端例如:https://github.com/localstack/localstack-python-client

    编辑: 我看到你的标题说明你想使用 moto。我没有看到您将 moto 任何 moto 模块导入您的代码。查看this page 中的最后一个sn-p 并将s3 替换为dynamodbdynamodb2(无论您使用哪个)

    【讨论】:

    • 您好,感谢您的回答,不幸的是我无法使用该答案,因为我只能使用 moto 来完成。我没有添加模块,因为我只是想大致了解如何实现它,所以只放了代码。
    猜你喜欢
    • 1970-01-01
    • 2020-09-16
    • 1970-01-01
    • 1970-01-01
    • 2022-11-06
    • 2021-12-24
    • 2021-06-14
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多