node.js 在请求规范中用 sinon stub AWS S3 方法

标签 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 stub ,有人能指出我正确的方向吗?

下面是当前工作的代码(带有包装器模块 s3wrapper.js,我想删除它并处理我的 status_router_spec.js 文件中的 stub )。换句话说,我希望能够调用 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

最佳答案

为了 @ippomakunochi 的利益而回答这个问题,他要求跟进回复。

我们最终使用了 rewire直接在 s3 库上设置 stub 。例如,我们使用以下代码对 s3 库的 getObject 调用进行了 stub :

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()
        })
      })
    })
  })

关于node.js 在请求规范中用 sinon stub AWS S3 方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29937045/

相关文章:

node.js - Fluent ffmpeg如何用户保存回调

javascript - 带有 sinon 返回函数的 stub 函数?

javascript - S3 使用流时上传损坏的文件

javascript - 使用 javascript 直接将超过 50 MB 的文件上传到 S3 存储桶

javascript - sinon.js 1.10、jquery 2.1 和同步请求

javascript - 使用 Sinon.js 测试 navigator.browserLanguage 或 navigator.language

node.js - Maven 未能执行目标 - 无法运行程序 npm

node.js - 如何摆脱 Node.js util.inspect 输出中的换行符?

javascript - 如何使用 Node 检查器在 "require"-d 库内设置断点?

node.js - 如何在 Node js 中从服务返回两个以上的值