jest unit test for AWS lambda

10,572

You can use jest.spyOn(object, methodName, accessType?) method to mock dataService.retrieveData method. And, your serviceFunction function only has one statement, so you can test lambdaService function with it together.

E.g.

index.js:

const dataService = require('./dataService');

exports.lambdaService = async event => {
  let response = await serviceFunction(event.id);
  if (response.code == 200) {
    return response;
  } else {
    return {
      statusCode: response.code,
      body: JSON.stringify({
        message: response.message
      })
    };
  }
};

const serviceFunction = async id => {
  return await dataService.retrieveData(id);
};

dataService.js:

module.exports = {
  retrieveData: async id => {
    return { code: 200, data: 'real data' };
  }
};

index.spec.js:

const { lambdaService } = require('.');
const dataService = require('./dataService');

describe('lambdaService', () => {
  beforeEach(() => {
    jest.restoreAllMocks();
  });
  test('should return data', async () => {
    const mResponse = { code: 200, data: 'mocked data' };
    const mEvent = { id: 1 };
    const retrieveDataSpy = jest.spyOn(dataService, 'retrieveData').mockResolvedValueOnce(mResponse);
    const actualValue = await lambdaService(mEvent);
    expect(actualValue).toEqual(mResponse);
    expect(retrieveDataSpy).toBeCalledWith(mEvent.id);
  });

  test('should return error message', async () => {
    const mResponse = { code: 500, message: 'Internal server error' };
    const mEvent = { id: 1 };
    const retrieveDataSpy = jest.spyOn(dataService, 'retrieveData').mockResolvedValueOnce(mResponse);
    const actualValue = await lambdaService(mEvent);
    expect(actualValue).toEqual({ statusCode: 500, body: JSON.stringify({ message: mResponse.message }) });
    expect(retrieveDataSpy).toBeCalledWith(mEvent.id);
  });

  test('should throw an error', async () => {
    const mEvent = { id: 1 };
    const retrieveDataSpy = jest.spyOn(dataService, 'retrieveData').mockRejectedValueOnce(new Error('network error'));
    await expect(lambdaService(mEvent)).rejects.toThrowError(new Error('network error'));
    expect(retrieveDataSpy).toBeCalledWith(mEvent.id);
  });
});

Unit test result with coverage report:

 PASS  src/stackoverflow/58623194/index.spec.js
  lambdaService
    ✓ should return data (6ms)
    ✓ should return error message (4ms)
    ✓ should throw an error (2ms)

----------------|----------|----------|----------|----------|-------------------|
File            |  % Stmts | % Branch |  % Funcs |  % Lines | Uncovered Line #s |
----------------|----------|----------|----------|----------|-------------------|
All files       |       90 |      100 |    66.67 |       90 |                   |
 dataService.js |       50 |      100 |        0 |       50 |                 3 |
 index.js       |      100 |      100 |      100 |      100 |                   |
----------------|----------|----------|----------|----------|-------------------|
Test Suites: 1 passed, 1 total
Tests:       3 passed, 3 total
Snapshots:   0 total
Time:        4.619s

Source code: https://github.com/mrdulin/jest-codelab/tree/master/src/stackoverflow/58623194

Share:
10,572
Prabhakaran
Author by

Prabhakaran

Updated on June 07, 2022

Comments

  • Prabhakaran
    Prabhakaran almost 2 years

    I am new to Node.js. I was trying to write a jest unit test cases for AWS lambda function(for node environment). I used a node module called "lambda-tester" to test it. But the problem with "lambda-tester" is, it will hit the actual service and return the data. I don't want to do that. I need to mock the service call.

    So, I wanted to go with the plain old way. But, I have issues with mocking it. Can you help me to write basic unit test case for the below lambda ith mocking the function "serviceFunction" ?

    const dataService = require('../dataService');
    
    exports.lambdaService = async event => {
      let response = await serviceFunction(event.id);
      if (response.code == 200) {
        return response;
      } else {
        return {
          statusCode: response.code,
          body: JSON.stringify({
            message: response.message
          })
        };
      }
    };
    
    const serviceFunction = async id => {
      return await dataService.retrieveData(id);
    };