首页 > 解决方案 > AWS lambda 的笑话单元测试

问题描述

我是 Node.js 的新手。我正在尝试为 AWS lambda 函数(用于节点环境)编写一个开玩笑的单元测试用例。我使用了一个名为“lambda-tester”的节点模块来测试它。但是“lambda-tester”的问题是,它会命中实际的服务并返回数据。我不想那样做。我需要模拟服务调用。

所以,我想走普通的老路。但是,我有嘲笑它的问题。你能帮我为下面的 lambda 编写基本的单元测试用例,并模拟函数“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);
};

标签: javascriptnode.jsaws-lambdajestjs

解决方案


您可以使用jest.spyOn(object, methodName, accessType?)方法来模拟dataService.retrieveData方法。而且,您的serviceFunction函数只有一个语句,因此您可以lambdaService一起测试函数。

例如

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

带有覆盖率报告的单元测试结果:

 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

源代码:https ://github.com/mrdulin/jest-codelab/tree/master/src/stackoverflow/58623194


推荐阅读