Beni Mio Beni Mio - 1 month ago 15
Node.js Question

Testing node callbacks with mocha

I try to extract method from an

async.waterfall
. I would like to test them separately. Here is the first method who invoke a lambda on AWS.

const async = require('async');
const AWS = require('aws-sdk');
AWS.config.region = 'eu-west-1';
const lambda = new AWS.Lambda();
const table_name = 'my_table';

exports.handler = function(event, context) {
async.waterfall([
increase_io_write_capacity(callback)
],
function (err) {
if (err) {
context.fail(err);
} else {
context.succeed('Succeed');
}
});
};

function increase_io_write_capacity(callback) {
var payload = JSON.stringify({
tableName:table_name,
increaseConsumedWriteCapacityUnits: 5
});
var params = {
FunctionName: 'dynamodb_scaling_locker',
InvocationType: 'RequestResponse',
Payload: payload
};

lambda.invoke(params, function(error, data) {
if (error) {
console.log('Error invoker!' + JSON.stringify(error));
callback('Invoker error' + JSON.stringify(error));
} else {
console.log('Done invoker!' + JSON.stringify(data));
callback(null);
}
});
}

if (typeof exports !== 'undefined') {
exports.increase_io_write_capacity = increase_io_write_capacity;
}


The test use
mocha
and
aws-sdk-mock
.

const aws = require('aws-sdk-mock');
const testingAggregate = require('../index.js');
const assert = require('assert');
const expect = require( 'chai' ).expect;
const event = '';

describe('Testing aggregate function', function () {
afterEach(function (done) {
aws.restore();
done();
});

describe('increase_io_write_capacity', function() {
it('fail accessing to the lambda', function(done){
aws.mock('Lambda', 'invoke', function(params, callback){
callback('fail', null);
});
testingAggregate.increase_io_write_capacity(function(err, data){
expect(err).to.equal('Error invoker! fail');
done();
});
});
});
});


The problem is it never assert. I go properly into the method but never into the
lambda.invoke
. It seems the mock never return the callback.

Testing aggregate function
increase_io_write_capacity
1) fail accessing to the lambda


0 passing (2s)
1 failing

1) Testing aggregate function increase_io_write_capacity fail accessing to the lambda:
Error: timeout of 2000ms exceeded. Ensure the done() callback is being called in this test.


If I try on a simple example in aws-sdk-mock codebase I don't have any issue.

t.test('mock function replaces method with replace function with lambda', function(st){
awsMock.mock('Lambda', 'invoke', function(params, callback){
callback("error", null);
});
var lambda = new AWS.Lambda();
lambda.invoke({}, function(err, data){
st.equals(err, "error'");
awsMock.restore('Lambda');
st.end();
})
})


Maybe I don't assert properly the result of the callback?

Thanks in advance for your help.

Answer

I failed using aws-sdk-mock

I finally used proxyquire. The code is not that clean, not DRY. I'm not a JS developper. But it works. Feel free to make changes.

const proxyquire = require('proxyquire').noCallThru();
const expect = require( 'chai' ).expect;

describe('testingAggregate', function() {
  describe('increase_io_write_capacity', function() {
    it('fail invoke the lambda', function(done){
      let awsSdkMock = {
        config: {
          region: 'eu-west-1'
        },
        Lambda: function() {
          this.invoke = function(params, callback) {
            expect(params.Payload).to.eq('{"tableName": "my_table_name","increaseConsumedWriteCapacityUnits":5}');
            callback(new Error('Lambda not in this region'));
          };
        }
      };
      let testingAggregate = proxyquire('../index', { 'aws-sdk': awsSdkMock });

      testingAggregate.increase_io_write_capacity(function(err, data){
        expect(err).to.equal('Invoker error: Error: Lambda not in this region');
      });
      done();
    });

    it('succeed invoking the lambda', function(done){
      let awsSdkMock = {
        config: {
          region: 'eu-west-1'
        },
        Lambda: function() {
          this.invoke = function(params, callback) {
            callback(null);
          };
        }
      };
      let testingAggregate = proxyquire('../index', { 'aws-sdk': awsSdkMock });

      testingAggregate.increase_io_write_capacity(function(err, data){
        expect(err).to.equal(null); //really not the best test
      });
      done();
    });
  });
});
Comments