AWS CDK - 如何在本地 运行 API 和 Lambdas?

AWS CDK - How to run API and Lambdas locally?

编辑:原来解决方案在文档中。我安装了沼泽标准正常 'sam',但我需要他们所谓的 'public preview version' AKA 'sam-beta-cdk'。安装后 API 可以在本地使用 sam-betacdk start-api 启动并且运行良好。虽然我很欣赏建议应该使用纯 TDD 进行开发的答案,但我认为这种更具交互性的手动模式也很有价值,因为它允许更快地探索问题 space.

我正在尝试使用 API Gateway、Lambdas 和 DynamoDB 使用 CDK + Typescript 构建我的第一个应用程序。我已经构建了几个 Lambdas 并部署了它们,它们在网络上运行良好。但是,我不希望将一分钟长的部署周期和各种相关的 AWS 成本作为我工作流程的一部分。我想要的是能够在本地测试我的 API。

我一直在努力寻找有关如何执行此操作的文档。 Amazon 似乎推荐使用 SAM CLI here,这就是我一直在尝试的。

文档声称 运行ning sam local xyz 运行s cdk synth./aws-sam/build 中进行“可能组装”,但我没有看到这方面的证据.相反,我得到的是 sam 找不到 'template.yml' 的投诉。所以我手动 运行 cdk synth > template.yml 在根文件夹中创建一个。然后我运行 sam local start-api 看来开机很开心

然后我尝试使用 CURL 访问我的测试 lambda:curl 'http://127.0.0.1:3000/test' 我在控制台中得到 {"message":"Internal server error"} 和一个巨大的丑陋堆栈跟踪 运行ning sam local start-api

lambda 是这个...

exports.handler = async function() {
    console.log("WooHoo! Test handler ran")
    return {statusCode: 200, headers: {"Content-Type": "application/json"}, body: "Test handler ran!"}
}

巨大丑陋的堆栈跟踪的开始...

Mounting /home/user/code/image-cache/asset.beeaa749e012b5921018077f0a5e4fc3ab271ef1c191bd12a82aa9a92148782e as /var/task:ro,delegated inside runtime container
START RequestId: 99f53642-b294-4ce5-a1b4-8c967db80ce1 Version: $LATEST
2021-09-15T12:33:37.086Z    undefined   ERROR   Uncaught Exception  {"errorType":"Runtime.ImportModuleError","errorMessage":"Error: Cannot find module 'test'\nRequire stack:\n- /var/runtime/UserFunction.js\n- /var/runtime/index.js","stack":["Runtime.ImportModuleError: Error: Cannot find module 'test'","Require stack:","- /var/runtime/UserFunction.js","- /var/runtime/index.js","    at _loadUserApp (/var/runtime/UserFunction.js:100:13)","    at Object.module.exports.load (/var/runtime/UserFunction.js:140:17)",

丑陋的巨大堆栈跟踪结束...

Invalid lambda response received: Lambda response must be valid json

所以看起来 sam local start-api 找不到 test 并抛出错误,这意味着 API 网关没有得到有效的 'lambda response'。到目前为止,这并没有帮助我追查问题:/它似乎确实意识到测试是一条路线,因为试图击中其他端点给出了经典的 {"message":"Missing Authentication Token"} 但是尽管我有两个 {"message":"Missing Authentication Token"} 但它很难尝试实现它 functions/test.ts 和编译的 functions/test.js 存在。

我在我的 CDK 堆栈定义中定义了测试路由和处理程序,就像这样...

    const testLambda = new lambda.Function(this, "testLambdaHandler", {
      runtime: lambda.Runtime.NODEJS_14_X,
      code: lambda.Code.fromAsset("functions"),
      handler: "test.handler"
    })

    api.root
      .resourceForPath("test")
      .addMethod("GET", new apigateway.LambdaIntegration(testLambda))

我考虑过发布我的 template.yml 但那比丑陋的大错误消息还要长所以我没有。

所以我有三个问题(实际上有一百万个问题,但我不想太厚颜无耻!)

  1. 这实际上是在本地测试使用 CDK 制作的应用程序的规范方法吗
  2. 如果是这样,我哪里错了?
  3. 如果不是,better/proper方法是什么?

您的文件目录一定有问题。您的 index.js 在哪里?如果生成 template.json,目录是否正确? 还有你在什么目录下执行Sam本地命令?

测试无服务器应用程序的关键是您不必测试整个应用程序。您需要依靠 AWS API 网关、dynamodb 和 lambda 完美运行。 您唯一需要测试的是您实现的逻辑。

在这里你要确保你的函数打印出一些东西和 returns 一个 200。这就是你所要做的。 查看 'jest' 以测试 js。

如果你想测试 cdk 你应该进入 https://docs.aws.amazon.com/cdk/latest/guide/testing.html

此外,“运行 Aws locally”也不是好的做法。它与现实生活中的 运行 完全不同,也就是云。你这个用插件,那个用工具……本地跟云端不一样。

如果您还有其他问题,请随时提问。

Lambda 处理程序只是函数。它们不需要任何特殊环境即可运行 - 它们在 Lambda 调用过程的特定点被调用,并提供一个事件(一个 json 对象)和一个上下文(另一个 json 对象)

您可以(并且应该!)像在 language/testing 框架中的任何其他单独函数一样对它们进行单元测试。

正如@Lucasz 所提到的,您应该相信这样一个事实,即如果设置正确,API 网关和 Lambda 每次都会以相同的方式进行交互。一旦你有 运行 一个端到端测试并且你知道基础工作,任何进一步的实现都可以通过单元测试完成

有许多库可用于在单元测试中模拟 AWS 服务调用,并且对于更难模拟的服务(即:很难从另一个 lambda 内部模拟 Lambda 调用)有很多好的实践解决方法- 但如果你将 lambda 调用包装在它自己的函数中,你可以将函数本身模拟为 return 任何你想要的 - 这也是测试的好习惯!)

使用 jest,在编码单元测试中,您可以调用 lambda 处理程序,给它存根或模拟事件 json,以及上下文 json(可能只是空白,因为你不是使用它)和 lambda 处理程序将像您曾经编写的具有两个参数的任何其他函数一样运行,包括 return 将您想要的内容 return.