LoginSignup
38
35

More than 5 years have passed since last update.

AWS SDKを使ってもAWS環境にアクセスせずにユニットテストを回す方法

Last updated at Posted at 2016-07-12

概要

aws-sdkを使ったライブラリなどのユニットテストを行うには特定のAWSアカウントが必要になります。AWSのアカウントを立ち上げてユニットテストをしてもいいんですが、どうしてもAWSアカウントに依存したり、ユニットテストの度にお金がかかります。

Travisでテストを回した時に、プルリクの度にテストが回ってお金がかかったり、IAMの設定がミスってて余計なAWSリソースを起動させられてしまったりとか、色々と考えないといけないことや制限が多くなります。

LambdaでCI環境を作る時も同じ悩みがつきものですね。
それを解決してくれるaws-sdk-mockというライブラリを見つけたので紹介します

aws-sdk-mockとは

スクリーンショット 2016-07-12 22.54.02.png
aws-sdk-mockとはaws-sdkのモックを簡単に作ってくれるライブラリです。
aws-sdkで定義されているメソッドのモックを定義してくれます。

今回はモックに関する細かい説明は省きますが、簡単にいえば、AWS環境にアクセスしなくても擬似的にaws-sdkの各メソッドの返り値を返してくれます。要はaws-sdkを使っていてもAWS環境にアクセスすること無くユニットテストが実施できるんです。

テスト対象のソースコード

今回は以下のClassを作ってみました。DynamoDBにputItem,getItem,deleteItemするメッソドが定義されてるClassです。

users.js
'use strict'

var aws = require('aws-sdk')
    aws.config.update({region:'ap-northeast-1'})

class Users {

  constructor() {
    this.table = 'Users'
    this.dynamodb = new aws.DynamoDB()
  }

  putData(email) {
    let params = {
      TableName: this.table,
      Item     : { 'email': {'S':email} }
    }

    return this.dynamodb.putItem(params).promise()
  }

  getData(email) {
    let params = {
      TableName: this.table,
      Key      : { 'email': {'S':email} }
    }

    return this.dynamodb.getItem(params).promise()
  }

  deleteData(email) {
    let params = {
      TableName: this.table,
      Key      : { 'email': {'S':email} }
    }

    return this.dynamodb.deleteItem(params).promise()
  }
}
module.exports = Users

以下のように直接実行するとちゃんとDynamoDBにレコードができています。

var user = new Users()
user.putData('panpanpan@example.com')

スクリーンショット 2016-07-12 23.07.04.png

テストコード

では次にモックを定義してテストコードを作ります。以下がテストコードのすべてです。
3つのメソッドの中で使っているaws-sdkに対してモックを定義しています。

users-spec.js
'use strict'

var aws    = require('aws-sdk-mock'),
    users  = require('../index'),
    chai   = require('chai'),
    path   = require('path'),
    should = chai.should(),
    input  = 'horike37@gmail.com',
    usersObj

aws.setSDK(path.resolve('node_modules/aws-sdk'))

describe('All Tests', function() {

  this.timeout(0)
  beforeEach(function() {
    aws.mock('DynamoDB', 'putItem', function(params, callback) {
      callback(null, 'successfully put item in database')
    })

    aws.mock('DynamoDB', 'getItem', function(params, callback) {
      callback(null, { Item: { email: params.Key.email.S } })
    })

    aws.mock('DynamoDB', 'deleteItem', function(params, callback) {
      callback(null, 'successfully delete item in database')
    })

    usersObj = new users()
  })


  it('putData', function(done) { 
    usersObj.putData(input).then(function(res) {
      res.should.equal('successfully put item in database')
      done()
    })
  })

  it('getData', function(done) {
    usersObj.getData(input).then(function(res) {
      res.Item.email.should.equal(input)
      done()
    })
  })

  it('deleteData', function(done) {
    usersObj.deleteData(input).then(function(res) {
      res.should.equal('successfully delete item in database')
      done()
    })
  })
})

DymanodbのputItemに対しては、問答無用でsuccessfully put item in databaseが返るようになっています

aws.mock('DynamoDB', 'putItem', function(params, callback) {
      callback(null, 'successfully put item in database')
    })

テストコードの実行

ちゃんとDynamoDBのUsersテーブルは消した状態で以下のようにテストを走らせると正しく実行されました。これでLambdaでもAWSリソースを使う前提のコードはテストをしていけそうですね!

スクリーンショット 2016-07-12 23.14.27.png

38
35
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
38
35