Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Sinon.Stub in Node with AWS-SDK

I am trying to write some test coverage for an app that uses the aws-sdk NPM module that pushes things up to a SQS queue, but I am unsure how to mock things correctly.

Here is my test so far:

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

    });

});

The error I am seeing is:

  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

I am a bit of a newb when it comes to sinon.stub or mocking objects in JavaScript, so please excuse my ignorance

like image 732
dennismonsewicz Avatar asked Oct 07 '14 19:10

dennismonsewicz


People also ask

What is AWS SDK mock?

AWSome mocks for Javascript aws-sdk services. This module was created to help test AWS Lambda functions but can be used in any situation where the AWS SDK needs to be mocked. If you are new to Amazon WebServices Lambda (or need a refresher), please checkout our our.

What is Sinon stub ()?

The sinon. stub() substitutes the real function and returns a stub object that you can configure using methods like callsFake() . Stubs also have a callCount property that tells you how many times the stub was called. For example, the below code stubs out axios.

What is Sinon sandbox?

JS. Sandboxes removes the need to keep track of every fake created, which greatly simplifies cleanup. var sandbox = require("sinon").

What is Sinon spy?

Sinon spies are used to record information about function calls. Unlike mocks or stubs, spies do not replace the function being called. Spies just record what parameters the function was called with, what value it returned, and other information about the function execution.


3 Answers

This is how I stub the AWS-SDK using sinonjs

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

Basically I control all the methods from the main SQS. Hope this will help someone

like image 167
kdlcruz Avatar answered Nov 13 '22 07:11

kdlcruz


We have created an aws-sdk-mock npm module which mocks out all the AWS SDK services and methods. https://github.com/dwyl/aws-sdk-mock

It's really easy to use. Just call AWS.mock with the service, method and a stub function.

AWS.mock('SQS', 'sendMessage', function(params, callback) {
    callback(null, 'success');
});

Then restore the methods after your tests by calling:

AWS.restore('SQS', 'sendMessage');
like image 44
Nikhila Ravi Avatar answered Nov 13 '22 07:11

Nikhila Ravi


I think the issue is that AWS SDK classes are built dynamically from JSON configuration. Here's the one for SQS: Github.

All API calls eventually make it down to makeRequest or makeUnauthenticatedRequest on Service, so I just stubbed those using withArgs(...). For example:

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

which worked fine for my simple use case.

like image 6
David Avatar answered Nov 13 '22 06:11

David