如何构造可测试性的lambda代码

时间:2019-03-28 15:00:20

标签: javascript node.js amazon-web-services aws-lambda

我正在尝试使用API​​网关,lambda和DynamoDB创建小型REST API,同时遵循TDD等良好的开发实践。我习惯于使用DI容器来配置我的对象,这非常适合进行模拟和测试。在MVC框架中,将只有一个入口点,在这里我可以定义容器配置,引导应用程序并调用控制器来处理事件。我可以独立于应用程序的其余部分来测试控制器,并注入模拟的依赖项。我无法弄清楚如何将lambda函数可能与lambda函数本身分离。例如:

const { DynamoDB } = require('aws-sdk')
const { UserRepo } = require('../lib/user-repo')

const client   = new DynamoDB({ region: process.env.REGION }) // Should be resolved by DI container
const userRepo = new UserRepo(client) // Should be resolved by DI container

exports.handler = async (event) => {
  return userRepo.get(event.id)
}

请任何人引导我正确构造lambda代码,以便对其进行正确的单元测试?

1 个答案:

答案 0 :(得分:2)

在我目前正在研究的项目中,我们采用的一种方法是分解需求,因此handler负责:

  • 创建客户;
  • 从环境中提取任何配置;和
  • 从事件中获取参数。

然后它调用另一个完成大部分工作的函数,我们可以单独对其进行测试。将handler视为控制器,将其他功能视为完成工作的服务。

在您的特定情况下,可能看起来像这样:

const { DynamoDB } = require('aws-sdk');
const { UserRepo } = require('../lib/user-repo');

const doTheWork = (repo, id) => repo.get(id);

exports.handler = async (event) => {
  const client = new DynamoDB({ region: process.env.REGION });
  const userRepo = new UserRepo(client); 
  return doTheWork(userRepo, event.id);
}

doTheWork现在可以在单元级别使用回购对象和所需输入的测试加倍来执行。 UserRepo已经通过Dynamo客户端的构造函数注入而解耦,因此也应该可以测试。

我们还进行了集成级别的测试,这些测试仅 模拟了AWS开发工具包的内容(您也可以使用传输层模拟或类似aws-sdk-mock的东西)以及端到端的测试来确保整体系统一起工作。