Sinon.使用AWS-SDK在Node中存根

den*_*icz 15 node.js sinon aws-sdk

我正在尝试为使用aws-sdkNPM模块的应用程序编写一些测试覆盖,该模块将事物推送到SQS队列,但我不确定如何正确地模拟事物.

这是我到目前为止的测试:

var request = require('superagent'),
    expect = require('chai').expect,
    assert = require('chai').assert,
    sinon = require('sinon'),
    AWS = require('aws-sdk'),
    app = require("../../../../app");

describe("Activities", function () {

    describe("POST /activities", function () {

        beforeEach(function(done) {
            sinon.stub(AWS.SQS.prototype, 'sendMessage');

            done();
        });

        afterEach(function(done) {
            AWS.SQS.prototype.sendMessage.restore();

            done();
        });

        it("should call SQS successfully", function (done) {
            var body = {
                "custom_activity_node_id" : "1562",
                "campaign_id" : "318"
            };

            reqest
            .post('/v1/user/123/custom_activity')
            .send(body)
            .set('Content-Type', 'application/json')
            .end(function(err, res) {
                expect(res.status).to.equal(200)

                assert(AWS.SQS.sendMessage.calledOnce);
                assert(AWS.SQS.sendMessage.calledWith(body));
            });
        });

    });

});
Run Code Online (Sandbox Code Playgroud)

我看到的错误是:

  1) Activities POST /activities "before each" hook:
     TypeError: Attempted to wrap undefined property sendMessage as function

  2) Activities POST /activities "after each" hook:
     TypeError: Cannot call method 'restore' of undefined
Run Code Online (Sandbox Code Playgroud)

当谈到或嘲笑JavaScript中的对象时,我有点新手sinon.stub,所以请原谅我的无知

Nik*_*avi 20

我们创建了一个aws-sdk-mock npm模块,该模块可以模拟所有AWS SDK服务和方法. https://github.com/dwyl/aws-sdk-mock

它真的很容易使用.只需使用服务,方法和存根函数调用AWS.mock.

AWS.mock('SQS', 'sendMessage', function(params, callback) {
    callback(null, 'success');
});
Run Code Online (Sandbox Code Playgroud)

然后通过调用以下方法在测试后恢复方法:

AWS.restore('SQS', 'sendMessage');
Run Code Online (Sandbox Code Playgroud)

  • 但是我们不能在一个服务中多次模拟一个方法. (2认同)

小智 16

这就是我使用sinonjs存根AWS-SDK的方法

import AWS from 'aws-sdk'
import sinon from 'sinon'

let sinonSandbox

const beforeEach = (done) => {
   sinonSandbox = sinon.sandbox.create()
   done()
}

const afterEach = done => {
   sinonSandbox.restore()
   done()
} 
lab.test('test name', (done) => {
    sinonSandbox.stub(AWS, 'SQS')
      .returns({
        getQueueUrl: () => {
          return {
            QueueUrl: 'https://www.sample.com'
          }
        }
    })
    done()
})
Run Code Online (Sandbox Code Playgroud)

基本上我控制主SQS中的所有方法.希望这会对某人有所帮助

  • 不知道为什么这个答案没有得到更多的爱,它很简单,并且完成了工作.我创建了它的一般化来处理promise模式(我喜欢使用) - 见下文 (4认同)

小智 6

我认为问题在于 AWS SDK 类是从 JSON 配置动态构建的。这是 SQS 的一个:Github

所有API调用最终使其下降到makeRequestmakeUnauthenticatedRequest服务,所以我只是存根使用这些withArgs(...)。例如:

var stub = sinon.stub(AWS.Service.prototype, 'makeRequest');
stub.withArgs('assumeRole', sinon.match.any, sinon.match.any)
    .yields(null, fakeCredentials);
Run Code Online (Sandbox Code Playgroud)

这对我的简单用例来说效果很好。


小智 2

我无法确切地告诉你为什么不能用Sinon 来存根aws sdk(也许一些JS 专家可以更好地解释这一点),但它与proxyquire配合得很好。

代理 Nodejs 的需求,以便在测试过程中轻松覆盖依赖项,同时保持完全不显眼。