入社して1年になろうとしている中、やっとdynamo周りのテストを書く気になりました。
今までdynamo周りのテストは本番テーブル見に行くの良くないしテスト書くの苦手だしテストにdynamoDB local用意するのは面倒だし...って言い訳をいっぱい作ってサボっていたのですが aws-sdk-mock なるものがあるとのことだったので使ってみました。
今回のテストは ava を使っています。
テーブルの内容
今回デモのテーブルとしてパーティションキーを user_id
として以下のような構造にしています。
そしてやりたいこととしては指定したユーザーIDの名前と年齢を取得する、というものです。
user_id | name | age |
---|---|---|
1 | yamada | 18 |
2 | suzuki | 20 |
本番のコード
models/demo.js
const AWS = require("aws-sdk");
class Users {
constructor() {
this.table = "demo";
this.dynamodb = new AWS.DynamoDB.DocumentClient({
region: "ap-northeast-1"
});
}
getData(userId){
const params = {
TableName: this.table,
Key: {
id: userId
}
};
return new Promise((resolve, reject) => {
this.dynamodb.get(params, (err, data) => {
if (err) {
console.error(err);
return reject(err);
} else {
return resolve(data.Item);
}
});
});
}
}
テストコード
tests/user.test.js
const test = require("ava");
const aws = require("aws-sdk-mock");
const path = require("path");
const testUserId = "1";
const Users = require("../../models/demo");
let allUserObj = {};
aws.setSDK(path.resolve("node_modules/aws-sdk"));
test.serial("prepare aws-sdk-mock environment", t => {
aws.mock("DynamoDB.DocumentClient", "get", function(params, callback) {
callback(null, { Item: { user_id: params.Key.user_id, name:"yamada", age:18 } });
});
allUserObj = new Users();
t.pass();
});
test.serial("get user info", t => {
const ansData = {
user_id: "1",
name: "yamada",
age: 18
};
return allUserObj.getData(testUserId).then(data => {
t.is(ansData, data);
});
});
callbackの第二引数の部分に仮にテーブルに入れておくデータを指定します。getだけでなくscanも同じ要領です。queryも。scanやqueryに関してはItemsの中身を複数個入れないといけないのでちょっと面倒でした...
✔ models › demo › prepare aws-sdk-mock environment
✔ models › demo › get user info
無事に通りました
これでローカルでdynamoのテストができるので本番テーブルに影響を与える心配も利用料取られる心配もなく安心してテストできます。
これからはテストをもう少し積極的にしていきます。
参考