如何使用 moto 模拟多个 dynamodb 表

How to mock multiple dynamodb tables using moto

我有一个创建函数,它使用 3 个 dynamodb 表。我如何模拟三个 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: An error occurred (ExpiredTokenException) when calling the Scan operation: The security token included in the request is expired

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

我相信this post is almost identical to yours. You could try this or utilize some of the other existing tools like localstack or dynamodb-local. The Python client for localstack for example: https://github.com/localstack/localstack-python-client

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

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

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

您示例中的 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(...)


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

中创建的

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