Home > Net >  sinon stub for lambda function which is inside another lambda
sinon stub for lambda function which is inside another lambda

Time:05-05

Am writing unit test case for my code, as am calling another lambda function inside my lambda am not sure how to mock the inner lambda value, so because of this my test case is getting timed out. Attaching my code below

Test case file

    "use strict";

const sinon = require("sinon");
const AWS = require("aws-sdk");
const expect = require("chai").expect;

const models = require("common-lib").models;
const { Organization } = models;

const DATA_CONSTANTS = require("./data/deleteOrganization");
const wrapper = require("../../admin/deleteOrganization");

const sandbox = sinon.createSandbox();

describe("Start Test updateOrganization", () => {
  beforeEach(() => {
    sandbox.stub(Organization, "update").resolves([1]);
  });

  afterEach(async () => {
    sandbox.restore();
  });


  it("Test 03: Test to check success returned by handler", async () => {
    const mLambda = {
      invoke: sinon.stub().returnsThis(),
      promise: sinon.stub(),
    };

    const response = await wrapper.handler(
      DATA_CONSTANTS.API_REQUEST_OBJECT_FOR_200
    );
    console.log({ response });
    expect(response.statusCode).to.be.equal(200);
    const body = JSON.parse(response.body);
    expect(body.message).to.be.equal("Updated successfully");
  });
});

Code function

  exports.handler = asyncHandler(async (event) => {
  InitLambda("userService-deleteOrganization", event);

  const { id } = event.pathParameters;

  if (isEmpty(id)) {
    return badRequest({
      message: userMessages[1021],
    });
  }
  try {
    const orgrepo = getRepo(Organization);

    const [rowsUpdated] = await orgrepo.update(
      { isDeleted: true },
      { org_id: id }
    );

    if (!rowsUpdated) {
      return notFound({
        message: userMessages[1022],
      });
    }
    const lambda = new AWS.Lambda({
      region: process.env.region,
    });

    await lambda
      .invoke({
        FunctionName:
          "user-service-"   process.env.stage   "-deleteOrganizationDetail",
        InvocationType: "Event",
        Payload: JSON.stringify({
          pathParameters: { id },
          headers: event.headers,
        }),
      })
      .promise();

    return success({
      message: userMessages[1023],
    });
  } catch (err) {
    log.error(err);
    return failure({
      error: err,
      message: err.message,
    });
  }
});


CodePudding user response:

It seems that you are not properly stubbing the AWS.Lambda object.

try this,

const sinon = require("sinon");
const AWS = require("aws-sdk");
const expect = require("chai").expect;

const models = require("common-lib").models;
const { Organization } = models;

const DATA_CONSTANTS = require("./data/deleteOrganization");
const wrapper = require("../../admin/deleteOrganization");

const sandbox = sinon.createSandbox();

describe("Start Test updateOrganization", () => {
    beforeEach(() => {
        sandbox.stub(Organization, "update").resolves([1]);
    });

    afterEach(async () => {
        sandbox.restore();
    });


    it("Test 03: Test to check success returned by handler", async () => {
        const mLambda = { invoke: sinon.stub().returnsThis(), promise: sinon.stub() };
        // you missed the below line
        sinon.stub(AWS, 'Lambda').callsFake(() => mLambda);

        const response = await wrapper.handler(
            DATA_CONSTANTS.API_REQUEST_OBJECT_FOR_200
        );
        console.log({ response });
        expect(response.statusCode).to.be.equal(200);
        const body = JSON.parse(response.body);
        expect(body.message).to.be.equal("Updated successfully");
        sinon.assert.calledOnce(AWS.Lambda);
        sinon.assert.calledWith(mLambda.invoke, {});
        sinon.assert.calledOnce(mLambda.promise);
    });
});

CodePudding user response:

I can see that, You are writing entire logic inside your handler function. This makes it less testable.

To overcome this you can write your code in such a way that is divided into small functions, which are easy to mock in test case files or testable independently. Handler function should only make call to those functions and return the result to the caller.

for Eg.

Lambda Handler:

exports.lambdaHandler = async (event) => {
  // do some init work here
  const lambdaInvokeResponse = await exports.invokeLambda(params);

}

exports.invokeLambda = async (params) {
  const response = await lambda.invoke(params).promise();
  return response;
}

test cases:

it('My Test Case - Success', async () => {
    const result = await app.lambdaHandler(event);
    const invikeLambdaResponse = {
       // some dummy response
    };
    sinon.replace(app, 'invokeLambda', sinon.fake.returns(invikeLambdaResponse ));
 });

This is now mocking the only lambda invoke part. You can mock all the external calls like this (dynamodb, invoke, sns, etc.) You can set spy and check if the called method is called as per desired arguments

  • Related