node.js使用sinon在请求规范中存根AWS S3方法

时间:2015-04-29 07:28:40

标签: node.js amazon-s3 sinon aws-sdk

我在express上运行了基于node.js 0.12.2的应用,该应用使用s3.headBucket中的aws-sdk 2.1.22方法返回JSON响应,具体取决于特定的存储桶存在与否。

我一直在努力用sinon直接发出对s3.headBucket的号召。我设法通过创建一个s3wrapper模块来解决这个问题,该模块只需要aws-sdk并实例化并返回s3变量,但是,我确信这可以在不使用的情况下完成包装模块,而不是直接与sinon衔接,任何人都可以指向正确的方向吗?

下面是当前正在运行的代码(包含我想要移除和处理s3wrapper.js文件中的存根的包装模块status_router_spec.js。换句话说,我希望能够拨打s3.headBucket({Bucket: 'whatever' ...而不是s3wrapper.headBucket({Bucket: ' ...,并能够使用我自己的回复来隐藏此s3.headBucket来电。

status_router_spec.js

var chai = require('chai'),
    sinon = require('sinon'),
    request = require('request'),
    myHelper = require('../request_helper')

var expect = chai.expect

var s3wrapper = require('../../helpers/s3wrapper')

describe('My router', function () {
  describe('checking the service status', function () {
    var headBucketStub

    beforeEach(function () {
      headBucketStub = sinon.stub(s3wrapper, 'headBucket')
    })

    afterEach(function () {
      s3wrapper.headBucket.restore()
    })

    describe('when no errors are returned', function () {
      it('returns healthy response', function (done) {
        // pass null to represent no errors
        headBucketStub.yields(null)

        request.get(myHelper.appUrl('/status'), function (err, resp, body) {
          if (err) { done(err) }
          expect(JSON.parse(body)).to.deep.eql({
            healthy: true,
            message: 'success'
          })
          done()
        })
      })
    })
  })
})

s3wrapper.js

var AWS = require('aws-sdk')
var s3 = new AWS.S3()

module.exports = s3

status_router.js

var Router = require('express').Router

var s3wrapper = require('../helpers/s3wrapper.js')

var router = new Router()

function statusHandler (req, res) {     
  s3wrapper.headBucket({Bucket: 'some-bucket-id'}, function (err) {
    if (err) {
      return res.json({ healthy: false, message: err })
    } else {
      return res.json({ healthy: true, message: 'success' })
    }
  })
}

router.get(/^\/status\/?$/, statusHandler)

module.exports = router

1 个答案:

答案 0 :(得分:0)

为@ippomakunochi的问题回答这个问题,他要求采取后续行动。

我们最终使用rewire直接在s3库上设置了一个存根。例如,我们使用以下命令将s3库的getObject调用存根:

s3stub = { getObject: sinon.stub(), listObjects: sinon.stub() }
revert = s3.__set__('s3', s3stub)

这是完整的代码:

../../../ build / app / helpers / s3

var AWS = require('aws-sdk');
var s3 = new AWS.S3();

module.exports = {
  get: function get(options, callback) {
    var requestOptions = { Bucket: module.exports.bucket(), Key: options.productId + '.json' };

    s3.getObject(requestOptions, function (err, data) {
      if (err) { // handle err }

        try {
          var productData = JSON.parse(data.Body);
        } catch (e) {
          // handle error
        }
        return callback(null, productData);
      });
    }
  }
}

test / unit / app / helpers / s3_spec.js

var AWS = require('aws-sdk')
var chai = require('chai')
var sinon = require('sinon')
var sinonChai = require('sinon-chai')
var chaiSubset = require('chai-subset')
var rewire = require('rewire')

var s3 = rewire('../../../build/app/helpers/s3')

chai.use(chaiSubset)
chai.use(sinonChai)

var expect = chai.expect

describe('S3', function () {
  var s3stub, revert

  beforeEach(function () {
    s3stub = { getObject: sinon.stub(), listObjects: sinon.stub() }
    revert = s3.__set__('s3', s3stub)
  })

  afterEach(function () {
    revert()
  })

  describe('#get', function () {
    context('when no errors are returned by s3', function () {
      it('returns a product', function (done) {
        var productResponse = helper.fixture.body('product.json')
        s3stub.getObject.yields(null, productResponse)

        s3.get({ productId: '1234' }, function (err, res) {
          expect(err).to.not.exist

          expect(res).to.containSubset({name: 'long sleeve shirt', 'retailer_code': 'retailer-1'})
          done()
        })
      })
    })

    context('when s3 returns a NoSuchKey error', function () {
      it('returns a NotFoundError', function (done) {
        var s3Error = AWS.util.error(new Error(), { name: 'NoSuchKey' })
        s3stub.getObject.yields(s3Error)

        s3.get({ productId: '1234' }, function (err) {
          expect(err.message).to.eql('1234 is not found in s3')
          expect(err.output.statusCode).to.eql(404)
          done()
        })
      })
    })
  })