Search code examples
node.jsunit-testingaws-lambdaamazon-dynamodbsinon

sinon stub for Lambda using promises


I just started using sinon, and I had some initial success stubbing out DynamoDB calls:

sandbox = sinon.createSandbox()
update_stub = sandbox.stub(AWS.DynamoDB.DocumentClient.prototype, 'update').returns({
  promise: () => Promise.resolve(update_meeting_result)
})

This works great.

But I also need to stub Lambda, and the same approach isn't working:

lambda_stub = sandbox.stub(AWS.Lambda.prototype, 'invoke').returns({
  promise: () => Promise.resolve({lambda_invoke_result}) // 
})

With this, I get the error: Cannot stub non-existent property invoke.

example implementation:

const AWS = require("aws-sdk")
AWS.config.update({region: 'us-west-2'})
const dynamodb = new AWS.DynamoDB.DocumentClient()
const lambda = new AWS.Lambda()

// lambda function handler
exports.handler = async (event) => {
  let result = await dynamodb.get({/* some get config */}).promise()
  // do stuff ...

  // kick off next lambda
  await lambda.invoke({/* lambda config */}).promise()

  return {"status": "ok"} // or something
}

Solution

  • Here is the unit test solution:

    index.js:

    const AWS = require('aws-sdk');
    AWS.config.update({ region: 'us-west-2' });
    const dynamodb = new AWS.DynamoDB.DocumentClient();
    const lambda = new AWS.Lambda();
    
    exports.handler = async (event) => {
      let result = await dynamodb.get({}).promise();
      await lambda.invoke({}).promise();
    
      return { status: 'ok' };
    };
    

    index.test.js:

    const sinon = require('sinon');
    const AWS = require('aws-sdk');
    
    describe('61516053', () => {
      afterEach(() => {
        sinon.restore();
      });
      it('should pass', async () => {
        const mLambda = { invoke: sinon.stub().returnsThis(), promise: sinon.stub() };
        sinon.stub(AWS, 'Lambda').callsFake(() => mLambda);
        const mDocumentClient = { get: sinon.stub().returnsThis(), promise: sinon.stub() };
        sinon.stub(AWS.DynamoDB, 'DocumentClient').callsFake(() => mDocumentClient);
    
        sinon.stub(AWS.config, 'update');
        const { handler } = require('./');
        await handler();
        sinon.assert.calledWith(AWS.config.update, { region: 'us-west-2' });
        sinon.assert.calledOnce(AWS.DynamoDB.DocumentClient);
        sinon.assert.calledOnce(AWS.Lambda);
        sinon.assert.calledWith(mLambda.invoke, {});
        sinon.assert.calledOnce(mLambda.promise);
        sinon.assert.calledWith(mDocumentClient.get, {});
        sinon.assert.calledOnce(mDocumentClient.promise);
      });
    });
    

    unit test results with 100% coverage:

      61516053
        ✓ should pass (907ms)
    
    
      1 passing (915ms)
    
    ----------|---------|----------|---------|---------|-------------------
    File      | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s 
    ----------|---------|----------|---------|---------|-------------------
    All files |     100 |      100 |     100 |     100 |                   
     index.js |     100 |      100 |     100 |     100 |                   
    ----------|---------|----------|---------|---------|-------------------