boto3 のインスタンス生成をグローバルで行っても moto を利用したユニットテストを成功させるには?
概要
記事一覧はこちらです。
moto を利用したユニットテストが成功しなくなるので boto3 のインスタンス生成を Lambda のハンドラー関数内で行うようにしていましたが、aws-lambda-powertools を試してみる(Tracer&X-Ray 編その2) で boto3 のインスタンス生成をグローバルで行った方が処理にかかる時間が短くなることが判明したため、boto3 のインスタンス生成をグローバルで行っても moto を利用したユニットテストが成功する方法を調べることにします。
今回は resize-image-app-project プロジェクトで作成した AWS Lambda のユニットテストを作成する(local動作版) でユニットテストを行った resize-image-app-project プロジェクトを使用します。
参照したサイト・書籍
- What about those pesky imports?
https://github.com/spulec/moto#what-about-those-pesky-imports
目次
手順
テスト対象のモジュールの import 文はテスト関数内に記述する
moto の GitHub の What about those pesky imports? に解決方法が書かれていました。import 文が関数の中に書けるとは思いませんでした。
resize_service/handler.py で s3_client = boto3.client('s3')
を記述する位置をハンドラー(resize 関数)の外側に移動してから、
import logging import os import re import uuid from urllib.parse import unquote_plus import boto3 from PIL import Image thumbnail_size = 320, 180 logger = logging.getLogger() logger.setLevel(logging.INFO) s3_client = boto3.client('s3') def resize_image(image_path, resized_path): with Image.open(image_path) as image: image.thumbnail(thumbnail_size) image.save(resized_path) def resize(event, context): for record in event['Records']: ..........
テストクラスの外に書いている from resize_service import handler
を、
import json import unittest import boto3 from moto import mock_s3 from resize_service import handler @mock_s3 class TestResizeService(unittest.TestCase): .......... def test_resize(self): s3_client = boto3.client('s3') s3_client.upload_file('tests/sample.jpg', TestResizeService.UPLOAD_BUCKET, 'sample.jpg') with open('tests/s3_event.json', 'r') as f: event = json.load(f) handler.resize(event, None) ..........
テスト関数内に移動します。
import json import unittest import boto3 from moto import mock_s3 @mock_s3 class TestResizeService(unittest.TestCase): .......... def test_resize(self): from resize_service import handler s3_client = boto3.client('s3') s3_client.upload_file('tests/sample.jpg', TestResizeService.UPLOAD_BUCKET, 'sample.jpg') with open('tests/s3_event.json', 'r') as f: event = json.load(f) handler.resize(event, None) ..........
python -m unittest -v
を実行するとテストは成功し、
IntelliJ IDEA 上でテストを実行しても問題なく成功します。
Docker 上で実行する方法も試してみましたが、問題なく成功しました。
履歴
2020/07/07
初版発行。