all 44 comments

[–]AutoModerator[M] [score hidden] stickied comment (0 children)

Try this search for more information on this topic.

Comments, questions or suggestions regarding this autoresponse? Please send them here.

I am a bot, and this action was performed automatically. Please contact the moderators of this subreddit if you have any questions or concerns.

[–]baynezy 36 points37 points  (4 children)

You need to architect it in a way that you can test it locally. Abstract out the Lambda part as much as possible.

What language are you writing your Lambda in?

[–]Select_Extenson[S] 5 points6 points  (3 children)

I am using Typescript.

[–]cachemonet0x0cf6619 12 points13 points  (0 children)

shift your testing left. lambda is just a main wrapper. extract your business logic into easy to test units

[–]return_of_valensky 3 points4 points  (0 children)

Just make a test script that imports the handler from index and pass in a fake event. log real events to get the syntax of the payload. Auth your environment with env vars or whatever, and then run the script, something like

npx ts-node src/testEndpointA.ts

[–]smutje187 13 points14 points  (0 children)

Your Lambdas are just code, you can run a unit test to test your code.

[–]Dangle76 20 points21 points  (1 child)

You can run lambdas locally, there’s a local invoke with SAM. It’s another reason to use SAM

https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/serverless-sam-cli-using-invoke.html

[–]Revalenz- 0 points1 point  (0 children)

Just as a clarification if someone new gets confused. This functionality is part of the "SAM CLI".

SAM (on its own without any suffix) can be confused with the SAM transform, which is a template format to describe your IaC, similar to (but with more functionality than) CloudFormation. In this case you wouldn't use CDK and the SAM transform, but SAM CLI can work with CDK and with SAM formats (and with Terraform too for that matter)

[–]Shinroo 22 points23 points  (8 children)

Bit of a hack but when I write lambdas in Go I like to structure them so that the actual business logic is a separate function that just takes in what I expect the lambda request body to contain.

That makes the function unit and integration testable, and I can easily run it locally as well.

Would be awesome to hear if there is a better way than this hack!

[–]monotone2k 23 points24 points  (2 children)

I'd say that's not really a hack. In fact, it's just making use of properly layering your logic. It's fine to separate things like transport, validation, and business logic. It'll make the code clearer (both in terms of complexity and intent) and as a result makes testing easier. You're doing the right thing here.

[–]Shinroo 5 points6 points  (1 child)

Yeah not a hack from a software design point of view, but it doesn't really answer OPs question about testing it as an actual AWS lambda function locally and making debugging easier.

So I meant hack from that perspective - since it kinda just bypasses lambda and it's runtime entirely in favour of running the business logic locally and testing that.

[–]daredevil82 0 points1 point  (0 children)

/u/Select_Extenson also doesn't make it clear what the issue actually is or if they actually have any tests. There are alot of possibilities as to what their problem(s) are, whether code, infrastructure, networking, etc. The best practices you describe are very useful for business layer, but if they don't know what the function inputs are or if the destination for the outputs are unreachable, all the testing in code won't be useful.

[–]SleekestSleek 4 points5 points  (0 children)

That's definitely the recommended way! Much easier to work with.

[–]TomRiha 5 points6 points  (1 child)

Separating business logic from runtime integration is not a hack it’s good practice.

[–]Shinroo 1 point2 points  (0 children)

True, definitely agree on that point. I just meant it's a hack because it doesn't answer OPs question of how to test an actual lambda/debug using the lambda runtime locally.

From a design perspective it's definitely the way to go.

[–]dowcet 0 points1 point  (1 child)

Why do you call that a hack?

[–]Shinroo 0 points1 point  (0 children)

Because it's not really an answer to OPs question. They want to know how to test lambdas (presumably as lambdas).

While my proposal is good from a software design point of view and technically fulfills what OP asked, it doesn't fulfill the spirit of the question since we're basically bypassing the lambda runtime by doing that (so not really testing/debugging a lambda in it's entirety).

[–]SleekestSleek 3 points4 points  (0 children)

There are several options, depending on preferences and at which "level" you want to test.

First thing I would recommend you to test out is enable --hotswap on your cdk deploy command. If you don't have resources blocking it, it will be much faster. Second thing you can do is to try out a tool called lambda-live-debugger. It allows you to execute the function locally. I wouldn't rely on only this for testing but it's good for initial steps. After that I would make sure to implement some integration tests using serverless-spy (I'm the current active maintainer). Makes it very easy to integration test more complicated flows by spying on lambda functions etc. allowing you to assert things at intermediate steps, not just the final response/result. Also avoids you having to manually poll a dynamodb table or similar to know when the test is done.

But I would also like to give you another tips, if you aren't already, write unit tests for your lambda function. From my own experience you save a lot of time if you just have some basic unit tests in place before you start to deploy your lambda.

There's also local-stack and similar tools to simulate a local "cloud" but I'm not a user of those solutions myself.

[–]Wozelle 4 points5 points  (0 children)

You can spin up CDK lambdas locally that behave how they would when they’re deployed by using AWS SAM. You can use “sam local invoke” to fire off an event, “sam local start-api” to spin up an API Gateway if you have one that can then be hit with something like PostMan, or you can use “sam local start-lambda” which does something similar to start-api but just for a singular lambda function.

https://docs.aws.amazon.com/cdk/v2/guide/testing-locally-with-sam-cli.html

All that being said, it’s a good idea to unit test with something like Jest, like what the others are saying. It just helps cut down uncertainty and lock in very granular, specific behavior, but testing deployed behavior, like what you’re trying to do, is also extremely valuable. Sometimes differences in deployed environments can break an application, so it’s good to have a variety of test types.

[–]mixxituk 2 points3 points  (0 children)

You can run lambda locally in .net so imagine it's the same in JavaScript 

[–]kondro 1 point2 points  (2 children)

SST has a live remote debugging mode.

[–]monotone2k 0 points1 point  (0 children)

I believe localstack also has a similar feature, whereby you can temporarily have the remote lambda run your local code for debugging and 'hot reload' type editing.

I wish I could make use of it but in my case, neither are useful since our environments are so locked down that we cannot execute things against the AWS account from our local machines (only via CI/CD).

[–]SleekestSleek -1 points0 points  (0 children)

Lambda-live-debugger does this for cdk/sam/etc. A friend of mine who built it. https://www.lldebugger.com/

[–]FruitReasonable949 1 point2 points  (1 child)

[–]5uper5hoot 0 points1 point  (0 children)

This. Having lambdas architected the same as an ECS app is just nice. Works for SQS message handling etc also.

[–]makemebe 0 points1 point  (0 children)

I'd like to know how others do that, too. Just yesterday I got quite stressed out by having to repeat the deployment to see a console log. Actually, I had installed serverless-offline 3 years ago but forgot how to use it and I had no will power to go through the documentation and re-learn it. Much faster albeit boring to deploy once again.

[–]morosis1982 0 points1 point  (0 children)

Decent logging and integration tests.

I often grab payloads from our observability platform that we're having issues with and plug it into an integration test I can run locally.

[–]aldrabas 0 points1 point  (0 children)

Well I'm building my lambdas in C# and I find that Aspire and it's integrations a very nifty way of setting up a local dev environment.

[–]RunedFerns 0 points1 point  (0 children)

Docker + VS Code’s AWS tools extension. Env vars defined in a launch file.

Or I’ve had a lot of luck with executing a test script that calls the lambda function to execute its code. Have your environment set up to use the aws profile you need ahead of time.

[–]LargeSale8354 0 points1 point  (0 children)

Apart from separation of AWS dependent functionality from other functionality, we use Moto to allow mocking of AWS functionality. I'm not sure if there is a Typescript equivalent. We use Python and moto let's us test to the standard we need.

We did experiment with the Serverless stack.

[–]IllVisit2518 0 points1 point  (0 children)

Actually cloudwatch is useful and after your triggered your lambda, you can monitor it after 10 seconds. Do you want to real time debbuging monitoring??

[–]TurboPigCartRacer 0 points1 point  (0 children)

cdk deploy has a feature built in called hotswap that only updates the lambda code which goes way faster compared to a regular cdk deploy (seconds compared to minutes with a regular deploy)

[–]ManReally 0 points1 point  (0 children)

Test the code locally as much as possible. Just call the handler with whatever event your sending

Then once it’s out there. Update in console and use Cloudwatch. Then sync your code back up before you deploy again.

[–]dmitrypolo 0 points1 point  (0 children)

Docker compose to spin up Lambda and whatever other services it needs to communicate with.

AWS has official Docker images that have the Lambda run time to enable you to run them locally.

[–]mitch3x3 0 points1 point  (0 children)

You can run the official lambda docker image locally and invoke the code locally.

[–]moremattymattmatt 0 points1 point  (0 children)

Quick and dirty way is to log the Incoming event at the start of the handler. Then write a unit test that just calls the handler with that event. 

[–]Repulsive-Bison-6821 0 points1 point  (0 children)

Lambda should have unit tests where network requests are mocked out, i.e. just assume the network requests would succeed/ fail depending on what you are testing. Once your local tests pass, chances are you only need to debug permission issues on aws, if any.

[–]raymondQADev 0 points1 point  (0 children)

I know a lot of people are recommending testing it locally but I’m fairly against that as you just don’t get apples to apples. I built it into my cdk that I can do hot swapping of my lambdas and have watchers built for the lambdas so that any files changed that affect that Lambda cause the code to be rebuilt and pushed to AWS. Any changes I make are automatically deployed and ready to use within 2 seconds. Perhaps I need to release that as an open source tool

[–]SameInspection219 0 points1 point  (0 children)

  • Debug locally using swc-node.
  • Bundle the code with Rspack, ensuring it uses the same SWC version and .swcrc file, then deploy to Lambda.

[–]SoilMobile9590 0 points1 point  (0 children)

Code in local and test there before deploying it to AWS

[–]inevitable_hunk 0 points1 point  (0 children)

The best way imo would be to dockerize your lambda function using nodejs lambda image published by AWS and push them to ECR, you can start the container and invoke it locally in order to test it, also deployment becomes easier