🤐

DynamoDBのエラーパターンをモックしてみた

2022/05/23に公開

DynamoDBを操作するpythonのunit testをする際に、正常系の確認はLocalStackを使用してテストしますが、エラーの場合どのようにモックすればいいのか苦労したので、メモしておきます。

https://docs.aws.amazon.com/ja_jp/amazondynamodb/latest/developerguide/Programming.Errors.html#Programming.Errors.TransactionalErrors

https://docs.aws.amazon.com/ja_jp/amazondynamodb/latest/APIReference/CommonErrors.html

テスト対象のプログラム

insert_todo/app.py
import boto3
import os


def lambda_handler(event, context):
    endpoint_url = os.getenv('ENDPOINT_URL')
    try:
        dynamoDB = boto3.resource("dynamodb", endpoint_url=endpoint_url)
        table = dynamoDB.Table("todo")

        response = table.put_item(
            Item={
                "user": event['user'],
                "time": event['time'],
                "title": event['title'],
                "contents": event['contents']
            })

        if response['ResponseMetadata']['HTTPStatusCode'] != 200:
            raise Exception(
                "DynamoDB put_item Error HTTPStatusCode: {}".format(
                    response['ResponseMetadata']['HTTPStatusCode']))

        return {"statusCode": 200}
    except Exception as e:
        print(e)
        return {"statusCode": 500}

テストコード

tests/unit/test_handler.py
from mock import MagicMock, mock
from insert_todo import app

@mock.patch('boto3.resource')
def test_insert_err_400(mock_boto3_resource):

    mock_table = MagicMock()
    mock_table.put_item = MagicMock(
        return_value={'ResponseMetadata': {
            'HTTPStatusCode': 400
        }})

    mock_dynamo = MagicMock()
    mock_dynamo.Table = MagicMock(return_value=mock_table)
    mock_boto3_resource.return_value = mock_dynamo

    event = {
        "user": "user1",
        "time": "time1",
        "title": "title1",
        "contents": "contents1"
    }

    ret = app.lambda_handler(event, "")
    assert ret["statusCode"] == 500

実行結果

sam-app $ python -m pytest tests/unit/test_handler.py -v -s                                                                                                                  
===================================================================================== test session starts ======================================================================================
platform linux -- Python 3.7.10, pytest-7.1.2, pluggy-1.0.0 -- /usr/bin/python3
cachedir: .pytest_cache
rootdir: /home/ec2-user/environment/sam-app
plugins: mock-3.7.0
collected 1 item                                                                                                                                                                               

tests/unit/test_handler.py::test_insert_err_400 DynamoDB put_item Error HTTPStatusCode: 400
PASSED

====================================================================================== 1 passed in 0.12s =======================================================================================

Discussion