Dean Mraz

I am passionate about delivering ideas and spending most of my time on product management techniques.

March 5th 2019

Testing Serverless Projects with Jest

serverless-jest-webpack

Serverless Framework makes developing and deploying serverless application easy, but lacks in defining the test implementation.

The Serverless Testing Guide provides greats concepts to follow, like:

  • Write your business logic so that it is separate from your FaaS provider (e.g., AWS Lambda), to keep it provider-independent, reusable and more easily testable.
  • When your business logic is written separately from the FaaS provider, you can write traditional Unit Tests to ensure it is working properly.

So, how do we follow those concepts?

Testing starts with understanding the Pyramid. The layers are Acceptance, Integration and Unit. Ideally you want to focus more on the Unit and Integration tests. In this tutorial, we will focus on setting up a project that can test the units and integrations.

Project Structure

  • We will start with the Serverless Framework configure for NodeJS and Webpack. If you need help on setup then checkout this tutorial.
  • We will code by separating out business and provider logic from the services and unit libraries.
  • We will leverage Jest. Jest focuses on simplicity and makes it easy to add code coverage, mocks and snapshots assertions.

Step 1

yarn add --dev jest

Step 2

  • Configure Jest jest.config.js
  • In this configuration we will setup the directories we want to be including in code coverage. Visit the docs for details on coverage thresholds
  • Also, I like using aliases with Webpack to utilize absolute instead of relative paths. Jest defines this as moduleNameMapper and uses babel under the hood.
// jest.config.js
module.exports = {

  collectCoverageFrom: ['./app/services/**/*.js'],

  coverageThreshold: {
    './app/services/**/*.js': {
      branches: 100,
      functions: 100,
      lines: 100,
      statements: 100,
    },
  },

  moduleNameMapper: {
    '@app(.*)$': '<rootDir>/app/$1',
  },
}

Step 3

  • Lets write some code for testing
// app/services/sum.js 

export default (a, b) => {
  return a + b;
};

export const random = () => {
  return Math.random();
};

Step 4

  • Lets write the Jest test
  • Note the @app from syntax, that is the moduleNameMapper mapping to <project directory>/app/services/sum
import sum from '@app/services/sum';

test('adds 1 + 2 to equal 3', () => {
  expect(sum(1, 2)).toBe(3);
});

Step 5

  • Run the test with coverage
jest --collectCoverage

jest-coverage

This setup allows us to separate out concerns.

  • Controllers should implement provider specific logic and source the business logic to the services or libraries.
  • Services code should have unit or integration tests with Jest.
  • Development cycles should improve because developing in units will have quicker feedback cycles.

Conclusion

In this tutorial we went over setting up Jest to test the units and integrations parts of the Test Pyramid. In the next few weeks, I'll go over the approach on the last piece of the Pyramid, which is running acceptance tests.

If you would like to see a working example you can check out this directory in my node-learning repository.

Lets chat on Twitter

Leave a comment by replying this tweet.