Unit testing code is a crucial step in creating automated continuous integration and continuous deployment pipelines for any application. Serverless applications are no different – in fact, the need for testing is greater in a system where the very hardware on which it runs is short-lived. In this article we’ll walk through how you can integrate a Jest test suite with your AWS Lambda serverless application written in NodeJS, giving you a command-line-testable application that can tie into any automated build tool you prefer.
The core of unit testing a Lambda function is getting access to the Lambda handler. All Lambda functions share the same function prototype in Node.js:
exports.lambdaHandler = async function(event, context)
This handler operates as any other asynchronous Node.js function would – you can simply import the function into your test file, and call the handler as you would with any other function (we’ll touch on the parameters in the next section). You’re then free to test the function as you would any other asynchronous Node.js function.
You can also leverage the synchronous handler prototype, if asynchronous calls are not well-suited to your goals:
exports.handler = function(event, context, callback)
Once you’ve settled on synchronous or asynchronous, you’ll need to install any dependencies for your Lambda application, just as you would when deploying the code to AWS.
There are three different parameters supplied to Node.js functions:
The event parameter is the parameter you will work with most heavily. The event parameter contains all of the information about the event triggering the function that is available. If this function was triggered against a message on an SQS queue, the SQS message will be present in the event parameter. For testing purposes, you can use this parameter with the same format as you would expect in production. It’s important to note that the format of the event parameter changes depending on the service you are working with.
The context parameter contains information on the current Lambda’s execution context. This includes billing information, such as the total number of invocations, the run time of your invocations, and other information that is critical to the context in which your application is executing. You can use this parameter to implement controls against Lambda itself, to prevent price overruns for example. The context parameter has the same format for each invocation.
The callback parameter is called by the Lambda function when the code is being executed synchronously. This code is then executed within the context of the parent application, giving you full access to any return values present in your Lambda function’s processing results.
Even with the straightforward steps above, there is still quite a bit of manual copy-and-paste that needs to take place before you can be unit testing in earnest. The AWS Serverless Application Model, or SAM, provides a number of tools that help ease this process. The most critical tool is available when constructing your input parameters for the function you are testing – sam generate-event. This command-line tool generates sample payloads from a number of different AWS services.
In addition to tools in support of unit testing, AWS SAM provides a number of tools that help facilitate local testing and deployment of your functions. It provides a template.yaml file for each suite of functions, closing the second-order classification hole that has long pained serverless apps written in Lambda. By providing a cohesive view of a serverless application along with an opinionated framework that encourages best practices, AWS SAM can help to further your development in every area.
Unit testing is a critical development practice that helps promote modularity in code while reducing the number of defects shipped to production. The ephemeral nature of the function execution context demands a robust testing scheme that can test all the possible logic holes in your application. Luckily, unit testing AWS Lambda functions is a straightforward process for Node.js applications. Simply import the handler function into your test file, then run your tests as you would with any other Jest test suite. AWS SAM can help make this process take minutes instead of hours through the addition of helpful tools that let you efficiently develop serverless functions on your local machine.