Node.js で Lambda ハンドラのテストを書くときに AWS イベントを生成する
Sunday, December 18, 2022 04:04:00 PM
AWS Lambda ハンドラをテストしたいとき、多くはリクエストのバリデーションの結果で 400 エラーを返すのか、ロジックが正常終了したとき 200 を戻すのか、みたいなことを書きたいことがあると思います。
TypeScript で Lambda ハンドラを記述する場合は、以下のようになると思います。
import { APIGatewayProxyHandler } from 'aws-lambda';
export const hello: APIGatewayProxyHandler = async (event) => {
// バリデーションやロジックの呼び出し
}
このとき event
は APIGatewayProxyEvent
型になるのですが、項目がたくさんあります。
自分で定義した interface などの場合、 factory.ts だったり、factory-bot みたいなライブラリを使って書けば良いのですが、 Lambda ハンドラのイベントはとても項目が多いので、 factory 定義を書くのも大変です。
faker-ts の利用
そこで以前は faker-ts というライブラリを使っていて @types/aws-lambda
から適当な値を生成していました。
import { tsMock } from 'faker-ts';
const mocker = tsMock(['/node_modules/@types/aws-lambda/index.d.ts']);
const event = mocker.generateMock('APIGatewayProxyEvent');
しばらくこの方法で問題はなかったのですが、 Node.js v16 と jest の組み合わせになり、メモリ不足エラーが出るようになってしまったので、見直しが必要になりました。
faker-ts の仕組み
faker-ts は以下の2つのステップから構成されていました。
- typescript-json-schema で TypeScript コードからJSONスキーマの生成
- json-schema-faker でJSONスキーマからJSONオブジェクトの生成
これを別々に実行して試していくプランとしました。
typescript-json-schema の利用
まずはJSONスキーマの生成から。 このNPMパッケージには CLI ツールも付いているので、npm script でスキーマファイルを生成できるようにしました。
"scripts": {
"tjs": "typescript-json-schema --required"
}
のように package.json に記述したら、コマンドを実行して JSONスキーマファイルを生成します。
$ npm run tjs -- -o test/schema/APIGatewayProxyEvent.json node_modules/@types/aws-lambda/index.d.ts APIGatewayProxyEvent
このようにして、必要な型のJSONスキーマを test/schema
の下に生成していきます。
json-schema-faker の利用
テストコードでは、以下のようにすることでJSONオブジェクトを生成します。
import { JSONSchemaFaker } from 'json-schema-faker';
import { faker } from '@faker-js/faker/locale/ja';
JSONSchemaFaker.option('useExamplesValue', true);
JSONSchemaFaker.option('useDefaultValue', true);
JSONSchemaFaker.option('faker', () => faker);
const event = <APIGatewayProxyEvent>JSONSchemaFaker.generate(require('test/schema/APIGatewayProxyEvent.json'));
event.body = /** テストで使う入力値 */
さいごに
これで TypeScript Interface から型定義に従った Fake オブジェクトが作れるようになりました。
faker-ts
はあまりメンテされていなかったので、コードを fork してライブラリを最新追従したりして使っていたのですが、その手間も不要となりました。
2つに処理を分割してわかったのは、 typescript-json-schema
が結構時間がかかっていたので、これを CLI にすることでメモリの利用状況も少なくなりました。
そのため、毎回JSONスキーマを生成しなくなった分、テストも速くなり良いことが多かったです。
この方法だと自分で作った TypeScript の型などでも一度 JSONスキーマを生成しておけば、複数の factory ライブラリを使わなくても良くなるので、良いかもしれません。(ただ現時点では factory-bot とかの方が使い勝手が良いとは思います。たとえば buildList みたいなことができないので)