AWS SDK를 사용해도 AWS 환경에 액세스하지 않고 유닛 테스트를 돌리는 방법

개요



aws-sdk를 사용하여 라이브러리와 같은 단위 테스트를 수행하려면 특정 AWS 계정이 필요합니다. AWS 계정을 시작하고 단위 테스트를 해도 괜찮습니다. 아무래도 AWS 계정에 의존하거나 단위 테스트마다 돈이 듭니다.

Travis에서 테스트를 돌렸을 때 풀릭마다 테스트가 돌려 돈이 들거나 IAM 설정이 잘못되어 불필요한 AWS 리소스를 시작할 수 있을지, 여러가지 생각해야 하는 일이나 제한이 많아집니다.

Lambda에서 CI 환경을 만들 때도 같은 고민이 붙는 것이군요.
그것을 해결해주는 aws-sdk-mock이라는 라이브러리를 발견했으므로 소개합니다.

aws-sdk-mock이란?




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('[email protected]')



테스트 코드



그런 다음 모의를 정의하여 테스트 코드를 만듭니다. 다음은 모든 테스트 코드입니다.
세 가지 방법 중에서 사용하는 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  = '[email protected]',
    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 리소스를 사용하는 전제 코드는 테스트를 할 수 있을 것 같네요!

좋은 웹페이지 즐겨찾기