Open6

AWS LambdaとDynamoDBのモックテストを作る

enumuraenumura

やりたいこと

  • AWS LambdaからDynamoDBにデータを書き込む処理をローカル環境でテストしたい
  • モックを使って簡単にUTしたい
enumuraenumura

環境構築

pip install pytest moto boto3
enumuraenumura

Lambdaを作成

簡単な処理を行うLambdaスクリプトを作成する。

lambda_function.py
import json
import boto3

dynamodb = boto3.resource('dynamodb')
table = dynamodb.Table('test-table')

def lambda_handler(event, context):    
    item = {
        'id': event['id'],
        'name': event['name']
    }
    # DynamoDBに接続してデータを書き込み
    table.put_item(Item=item)
    
    # 書き込んだデータを取得して返却
    response = table.get_item(Key={'id': event['id']})
    return {
        'statusCode': 200,
        'body': json.dumps(response['Item'])
    }
enumuraenumura

テストコードを作成

test_lambda_function.py
import json
import boto3
import pytest
from moto import mock_aws
from lambda_function import lambda_handler

@mock_aws
def test_lambda_function():
    # モックのDynamoDBテーブル作成
    dynamodb = boto3.resource('dynamodb')
    table = dynamodb.create_table(
        TableName='test-table',
        KeySchema=[{'AttributeName': 'id', 'KeyType': 'HASH'}],
        AttributeDefinitions=[{'AttributeName': 'id', 'AttributeType': 'S'}],
        BillingMode='PAY_PER_REQUEST'
    )
    
    # Lambdaに渡すテストデータ
    event = {
        'id': '1',
        'name': 'test'
    }

    # テストデータでLambda関数実行
    result = lambda_handler(event, None)
    # statusCodeが200か評価
    assert result['statusCode'] == 200
    
    body = json.loads(result['body'])
    # nameが'test'か評価
    assert body['name'] == 'test'
enumuraenumura

設定

warnを無視する場合

pytest.ini
[pytest]
filterwarnings =
    ignore::DeprecationWarning:botocore.*
enumuraenumura

動作確認

テスト実行

# 詳細情報を表示して実行
pytest test_lambda_function.py -v

テストが成功すれば以下のような出力。

=================================================== test session starts ====================================================
~~~~
test_lambda_function.py::test_lambda_function PASSED                                                                  [100%]

==================================================== 1 passed in 0.62s =====================================================