我正在尝试使用 API 网关、lambda 和 DynamoDB 制作一个小型 REST API,同时遵循 TDD 等良好的开发实践。我习惯于使用 DI 容器来提供我的对象,这非常适合模拟和测试。在 MVC 框架中,会有一个入口点,我可以在其中定义容器配置、引导应用程序并调用 Controller 来处理事件。我可以独立于应用程序的其余部分测试 Controller ,并注入(inject)模拟依赖项。我不知道如何将 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 代码的正确方向,以便对其进行正确的单元测试?
最佳答案
在我目前从事的项目中,我们采用的一种方法是拆分需求,因此 handler
负责:
- 创建客户;
- 从环境中提取任何配置;和
- 从事件中获取参数。
然后它调用另一个函数来完成大部分工作,我们可以单独测试它。将 handler
想象成 Controller ,将其他功能想象成完成工作的服务。
在您的特定情况下,这可能看起来像:
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
现在可以在单元级别使用 repo 对象的测试替身和您想要的任何输入来练习。 UserRepo
已经通过 Dynamo 客户端的构造函数注入(inject)解耦了,所以它也应该非常容易测试。
我们还在集成级别进行测试,仅 模拟 AWS SDK 的东西(您也可以使用传输层模拟或类似 aws-sdk-mock
的东西)以及确保整个系统正常工作的 E2E 测试一起。
关于javascript - 如何构建 lambda 代码以实现可测试性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55400782/