The project consists of an AWS Lambda function, and an Amazon DynamoDB table. Although this project can be deployed, the focus of the code is to demonstrate local testing approaches using TypeScript. This project demonstrates testing an AWS Lambda function handler locally which calls remote cloud services. The Lambda function handler makes a call to a DynamoDB table in the cloud in the integration test.
- Introduction
- Contents
- About this Pattern
- About this Example
- Sample project description
- Integration Test
- Cleanup
The SUT in this pattern is an AWS Lambda function that makes calls to other AWS cloud services using an AWS SDK. For this example, we demonstrate a system that generates a new item, written to an Amazon DynamoDB table by the Lambda function.
This pattern is intended to increase development speed. It enables rapid development and testing of a Lambda function that makes calls to other AWS cloud services using an AWS SDK. This pattern eliminates the need to perform a build and deploy of the Lambda function to the cloud between modifications of test or function code.
In this pattern you develop a Lambda function that makes calls to Amazon DynamoDB using an AWS SDK. Your tests invoke the handler function method on your local desktop, passing it a synthetic event as a parameter. The handler function executes within your local desktop environment. When the SDK invokes the Amazon DynamoDB table, it uses the AWS credentials contained in your local environment, typically as environment variables. The SDK calls resources deployed to the cloud.
In this sample, we have used AWS CDK (Cloud Development Kit) for infrastructure as code but the pattern can be also be used with a variety of systems including SAM, Serverless Framework, CloudFormation and Terraform. This pattern simplifies the process of attaching a debugger to the handler code. You may generate synthetic events using several methods including the ‘sam local generate-event’ command, by copying event template samples in the AWS Lambda console test section, or by printing events to CloudWatch logs.
The IAM policies contained in your local environment variables may differ from those contained in the execution role attached to the Lambda function in the AWS cloud environment. Therefore this pattern may not accurately test IAM permissions. You may mitigate this risk by using the IAM Roles Anywhere service to obtain temporary security credentials for the same execution role that the Lambda function uses in the cloud context. This service is open source and you may view the code on GitHub.
This example contains an AWS Lambda function and Amazon DynamoDB table as core resources.
AWS CDK is used to deploy the AWS Lambda function and Amazon DynamoDB table. The AWS Lambda function generates an item in the JSON format and writes this item to the DynamoDB table using the AWS SDK. The DynamoDB table item is a JSON object with format:
{
"ID": "string",
"created": "date",
"metadata": "json"
}
- app.ts - Lambda handler code to test
- lambda-handler-dynamodb-stack.ts - CDK stack for deploying required resources
- integ-handler.test.ts - Integration tests on a live stack
In order to run integration tests in the cloud we will first need to deploy the full CDK stack which will create a Lambda function and DynamoDB table in your AWS account. The integration test invokes the handler function method on the local machine, passing it a synthetic event as a parameter. The handler function executes within your local environment. When the SDK writes to DynamoDB, it uses the AWS credentials contained in your local environment.
Deploy the full stack:
lambda-handler-dynamodb$ npm install
lambda-handler-dynamodb$ cdk deploy
The integration tests need to be provided a single environment variable: DatabaseTable
, which is the name of the DynamoDB table providing persistence. It is available as DynamoDbTableName
in the CloudFormation outputs shown after the cdk deploy
step.
Set up the environment variable, replacing the <PLACEHOLDERS>
with your values:
lambda-handler-dynamodb$ export DatabaseTable=<YOUR_DYNAMODB_TABLE_NAME>
Then run the test suite.
lambda-handler-dynamodb$ npm run test
Alternatively, you can set the environment variables and run the test suite all in one command:
lambda-handler-dynamodb$ DatabaseTable=<YOUR_DYNAMODB_TABLE_NAME> npm run test
In order to delete the sample application that you created, use the AWS cdk command as shown below:
lambda-handler-dynamodb$ cdk destroy