Unit testing for Node.js Serverless projects with Jest
Tags: jest, node, serverless, tutorial
Published: 2022-03-29 14:39:25

Originally posted at [Serverless](https://www.serverless.com/blog/unit-testing-nodejs-serverless-jest)

Have you recently found yourself wondering how to write unit tests for your Serverless project? Well, good news. I’m here to talk about just that.

As the size and complexity of your Serverless project grows, automated testing becomes the key to creating clean abstractions, getting fast feedback, and maintaining the sanity of your team.

In this post, we will cover the basics of creating unit tests for Node.js projects using the [Serverless Framework](https://serverless.com/framework/). We will also show you how to run those tests on CI and provide some tips on writing good unit tests for your Serverless project.

**Note:** The example project is available on GitHub [here](https://github.com/chief-wizard/serverless-jest-example). We’ll also cover some resources to check out for next steps at the [bottom of the post](https://www.serverless.com/blog/unit-testing-nodejs-serverless-jest#resources).

Ready? Let’s go.

## Choosing your test framework

I’m a huge Jest fan when it comes to testing frameworks. Why?

 1. there’s zero configuration needed to get started

 2. it includes a good test runner

 3. has built-in functionality for mocks, stubs, and spies

 4. and has built-in code coverage reporting

To add Jest to your project, run yarn add --dev jest, and you should be good to go.

## Setting up the project

We decided to start with a fresh copy of the [aws-node-simple-http-endpoint](https://github.com/serverless/examples/tree/master/aws-node-simple-http-endpoint) example in this section:
{% gist https://gist.github.com/richardgrantserverless/b672eba78d699e060dbbc5c758ec25b1.js %}
The default endpoint in that example is quite simple, which is great for our case:
{% gist https://gist.github.com/richardgrantserverless/1e007276c439178bafd5160615e7fe52.js %}
We decided that we want it to say hello to the requester in a different language every time, so we added two functions that would generate a localized greeting:
{% gist https://gist.github.com/richardgrantserverless/76c8057ca1129d0e4165b35c84057a54.js %}
We then changed the main handler slightly to make use of these two functions:
{% gist https://gist.github.com/richardgrantserverless/df364bd79e171d0185d6327dda24cf77.js %}
And then tested the function locally:
{% gist https://gist.github.com/richardgrantserverless/84a681d14054b17733938be0a29304a7.js %}
## Creating tests

To make sure that our local greeting generation is working as expected, we decided to create a Jest unit test for the getLocalGreeting function.

For your tests to be picked up by Jest automatically, they either need to be placed in the __tests__ directory of your project, or include the word test or spec in the filename. This [can be configured easily](http://jestjs.io/docs/en/configuration#testregex-string) in Jest options if you prefer a different layout.

Let’s go ahead and create the __tests__ directory and add a handler.test.js file in it. The overall structure looks like this:
{% gist https://gist.github.com/richardgrantserverless/744b8ae2269623547e183fc64cd7fcbb.js %}
To be able to reference functions from handler.js in the test file, we need to export the function we're about to test:
{% gist https://gist.github.com/richardgrantserverless/8163344864d6672e2e2cdf0430c854e5.js %}
In the handler test file, we load the handler.js file and add two assertions for the local greeting function. One of those assertions is explicitly incorrect, so that we check if errors actually display correctly:
{% gist https://gist.github.com/richardgrantserverless/5445b010060afd58771ae0e9cf8ab46a.js %}
## Running tests

We can run tests for the first time by running yarn run jest in the root directory of the project with no parameters supplied. We should get the expected failure back:
{% gist https://gist.github.com/richardgrantserverless/a76a1db1fdd19733a130fce3f31be5d3.js %}
After replacing 🌊 with 👋 in the test’s assertion, all the tests pass:
{% gist https://gist.github.com/richardgrantserverless/4fec32437618cd7d0203530931826eb3.js %}
Nice!

## Running unit tests on CI

Getting the tests running on CI is straightforward — just invoke jest the same way you would in development. On CI services, you also generally need to add extra configuration for things like installing and caching of dependencies, and execution controls.

We tested our function on [CircleCI](https://circleci.com/) with the following config:
{% gist https://gist.github.com/richardgrantserverless/43c79e2d1dc1ffcd113f3202030acc45.js %}
## Test folder layout

As more test cases get added to the project, it is important to keep a consistent file and folder structure within our __tests__ folder. I advocate keeping the structure in the test directory as close as possible to the application file layout.

If we were to extract the getLocalGreeting function into its own greeting.js file, we would also extract the tests for it into __tests__/greeting.test.js. Had we decided to add folders in our project specific to models, views, or controllers, we would also make sure to place the tests accordingly:
{% gist https://gist.github.com/richardgrantserverless/8b2e842ba6cfa5bfab441e74bca6d097.js %}
## Unit test recommendations for Serverless projects

To make sure that the unit tests for your Serverless project are adding value to your development process and not being an annoyance for your team, I recommend following the unit testing best practices.

## Keep the unit tests fast and constrained

The best unit tests are the ones that cover a specific component of the system. This ensures that each individual test runs fast enough to be executed on developer machines during the development process and on CI.

## Use mocking where necessary

Mocking is a powerful tool (which Jest [provides](http://jestjs.io/docs/en/mock-functions) good functionality for). For parts of your Serverless project that interact with external databases like DynamoDB or third-party systems like Stripe, I recommend mocking out the external requests to ensure that your test suite does not depend on the third-party services being available and to reduce the latency of the test runs.

Keep in mind that mocking out an external API might hide the changes in that external API. Make sure to regularly validate the mocks against the recent third-party APIs if you decide to mock out important parts of the project in tests.

## Unit tests are not a full test suite by themselves

Unit tests are best used as guidelines for adequate component design and to validate the correctness of individual components. In your Serverless project, however, you will likely need to check whether different components of your project work correctly together via integration tests. I’d recommend using Jest for integration testing as well.

## Conclusion

Unit tests are only one part of a successful testing strategy. In addition to unit tests, writing integration tests, end-to-end tests, and performing manual validation will help you ensure the quality of your Serverless applications.

In this post, we talked about why pick Jest as the unit testing framework for your Serverless projects, how to write tests, how to structure the test files and how to execute tests on CI. I hope this will help you get started with testing your Serverless projects!

I’d also highly encourage you to check out the resources below, in order to learn more about Jest and other JavaScript testing frameworks. And while you’re at it, share your own testing tips [with the community](https://forum.serverless.com/)!

Please drop a comment with any feedback — I’d love to hear from you!

## Resources

* [Serverless HTTP endpoint example with the Jest test](https://github.com/chief-wizard/serverless-jest-example)

* [Jest documentation](http://jestjs.io/docs/en/getting-started)

* [CircleCI documentation reference](https://circleci.com/docs/2.0/configuration-reference/)