背景
Lambdaで実行する関数で使っているAWS-SDKをv2からv3に移行するに伴って、単体テストコードも修正が必要になった。
この記事は、v3における単体テストでAWSの各サービスへのアクセスをMockにする方法と、テストの実施方法についての記事になります。
準備
v2の時にはaws-sdk-mockを使っていたが、v3ではaws-sdk-client-mockを使う。
また、jestでのテストを便利にするためにaws-sdk-client-mock-jestも使用する。
npm i aws-sdk-client-mock aws-sdk-client-mock-jest
テストコード
Mockの作成
require("aws-sdk-client-mock-jest");
const { mockClient } = require('aws-sdk-client-mock');
const { DynamoDBDocument } = require('@aws-sdk/lib-dynamodb');
const { CognitoIdentityProvider } = require('@aws-sdk/client-cognito-identity-provider');
const { SES } = require('@aws-sdk/client-ses');
// 省略
beforeAll(() => {
DynamoDBMock = mockClient(DynamoDBDocument);
CognitoIdentityProviderMock = mockClient(CognitoIdentityProvider);
SESMock = mockClient(SES);
});
mockClientに各サービスを渡してあげればよい。
結果を編集する
テストに応じてAWSの各サービスから返ってくる値を変更したい場合は下記のようにする
// DynamoDBは使うコマンドも読み込んでおく
const { QueryCommand,PutCommand,DeleteCommand } = require('@aws-sdk/lib-dynamodb');
// 省略
beforeEach(() => {
DynamoDBMock.reset();
CognitoIdentityProviderMock.reset();
SESMock.reset();
DynamoDBMock.on(QueryCommand).resolves({ Items: [] });
DynamoDBMock.on(PutCommand).resolves({});
CognitoIdentityProviderMock.onAnyCommand().resolves({});
SESMock.onAnyCommand().resolves({});
});
作成したモックに対してonでコマンドを指定し、resolvesに返したい値を設定すればよい。
全てのコマンドを一括で設定する場合はonAnyCommandを使う。
結果を呼び出した順番に応じて変える
DynamoDBMock.on(QueryCommand)
.resolvesOnce({
Item: [],
})
.resolvesOnce({ Items: [{
ID:XXX,
Name:XXXXXX
}] })
.resolves({ Items: [] });
resolvesOnceを使うと最初の1回だけ返したい値を変更できる。
また、resolvesOnceを続けて記述することで2回目の呼び出し、3回目の呼び出し・・・と返したい値を設定できる。
最後にresolvesをつけておけばそれ以降の呼び出し全ての返したい値を設定できる。
例外をスローさせる
CognitoIdentityProviderMock.onAnyCommand().rejects({ code: 'UserNotFoundException' });
CognitoIdentityProviderMock.onAnyCommand()
.rejectsOnce({ code: 'UserNotFoundException' })
.resolves({});
rejectsを使うと例外をスローさせることができる。
また、rejectsOnceを使えば呼び出し回数に対応して例外を出すこともできる。
課題
- ヘイロードに応じて返す値を変えることもできるようだが、v2の時のテストでonCall(n)を使っていたものを移行したので今回は使用せず、ここに説明を挙げることができなかった
- Cognitoでコマンドを限定して返す値を設定する方法がわからかった。
上記、特に2つ目の件で何か情報をお持ちの方いましたらぜひコメントください。