Jest is an open-source JavaScript testing framework developed by Facebook. It is designed to make testing JavaScript code, whether it’s for web applications, server-side Node.js applications, or anything in between, a breeze. Jest has gained widespread adoption in the JavaScript community due to its user-friendly nature and powerful capabilities.
1. Zero Configuration: One of Jest’s standout features is its “zero configuration” setup. Out of the box, it provides sensible defaults that work for most projects. This means you can start writing tests almost immediately without spending time configuring the testing environment.
2. Fast and Parallel Execution: Jest is built to be fast. It can run tests in parallel, optimizing test suite execution time, and providing quick feedback to developers. This becomes particularly valuable as your codebase grows.
3. Snapshot Testing: Snapshot testing is a unique feature of Jest. It allows you to capture the output of a component or function and compare it to a previously saved “snapshot.” This is incredibly useful for detecting unexpected changes in your UI or data structures.
4. Mocking: Jest provides a robust mocking system for isolating the code you’re testing from external dependencies or modules. This helps you focus on testing the specific functionality you’re interested in, without worrying about the behavior of external components.
5. Async Testing: Asynchronous code is prevalent in JavaScript, and Jest handles it seamlessly. It supports async/await, Promise testing, and various mechanisms for dealing with asynchronous operations.
6. Code Coverage: Jest can generate code coverage reports, showing you which parts of your code are covered by tests. This helps you identify areas that need more testing and ensures that your test suite is comprehensive.
7. Custom Matchers: Jest allows you to create custom matchers for your test assertions. This tailoring your tests to your specific use cases makes them more expressive and readable.
8. Test Suites: Organize your tests into test suites and test cases, making it easy to manage and run specific sets of tests. This organization helps keep your test code clean and maintainable.
9. Continuous Integration (CI): Jest integrates smoothly with continuous integration and continuous deployment (CI/CD) pipelines. It can be configured to run tests automatically whenever code changes are pushed, ensuring that new code doesn’t introduce regressions.
10. Community and Ecosystem: Being backed by Facebook and with a large community of contributors, Jest has a rich ecosystem of plugins and extensions. This means that if you have a specific testing need, there’s likely a Jest plugin for it.
To get started with Jest, you need to install it (usually via npm or yarn) and create your test files with a .test.js or .spec.js extension.
npm install --save-dev jest
Jest will automatically find and run these tests. Writing tests in Jest is straightforward and typically follows the "Arrange, Act, and Assert" pattern.
Here’s a simple example of a Jest test:
export const getSum = (a: number, b: number) => {
// in index.ts
return a + b;
}
import { getSum } from '../index.js'
test('adds 1 + 2 to equal 3', () => {
// in getSum.test.ts
expect(getSum(1, 2)).toBe(3);
});
PASS ./sum.test.js
✓ adds 1 + 2 to equal 3 (5ms)
Let’s say we have a service say UserService, we are using Serverless Framework to build resources on the top of AWS provider :
service: userservice # Serverless.yml
package:
patterns:
- ../config/**
plugins:
- serverless-plugin-typescript
- serverless-offline
- serverless-prune-plugin
provider:
name: aws
versionFunctions: false
apiGateway:
minimumCompressionSize: 1024
runtime: nodejs18.x
region: ap-south-1
lambdaHashingVersion: 20201221
environment:
NODE_ENV: ${env:NODE_ENV, 'PreProd'}
timeout: 30
stage: Prod
iam:
role:
.....
custom:
prune:
automatic: true
number: 1
functions:
getUser:
handler: src/index.getUser
// in src/index.ts
export const getUser = async (event:any,context:any,callback:any) =>{
try{
const {userId}=event;
if(!userId){
throw new BadRequestError('Invalid Input');
}
// return the user from Db with statusCode 200
}catch{
console.error('Failed to get User', error);
}
So far we have our getUser function and a lambda in serverless.yml
So when we deploy our Service, Serverless will create a Stack with the name “userService-prod”, now we write some test data in our test-data folder 1) Invalid userId case 2) Valid userId case 3) userId is missing
{ // invalid-user-id.json
"userId": // Expected Error 404 (Resource not found)
}
{ // valid-user-id.json
"userId": // Expected Error 200 (Success)
}
{ // missing-user-id.json
// missing userId or empty userId // Expected Error 400 (Bad Request)
}
Jest Setup :
{ // package.json
.....
"scripts": {
.....
"test": "NODE_ENV=PreProd jest"
},
.....
}
We create the file jest.config.ts
{ // jest.config.ts
preset: 'ts-jest',
testEnvironment: 'node', // environment
collectCoverage: true,
coverageThreshold: {
global: {
branches: 10,
functions: 10,
lines: 10,
statements: 10
}
}
}
we create a Jest-setup-env.ts file:
This code fetches environment variables from an AWS Lambda function configuration and makes them available in the Node.js environment for further use, likely for configuration and initialization purposes.
export const setUpEnv = async (functionName: string) => {
// setting environment required for the test function/test suite
};
We add all test suits in __test__ folder like <function>.test.ts:
import { test, beforeAll, expect, describe, jest } from '@jest/globals';
import { getUser } from '../../src/index';
import { setUpEnv } from '../../set-up-env';
beforeAll(async () => {
await setUpEnv('getUser'); // set the environment for getUser Lambda function
jest.spyOn(console, 'log').mockImplementation(() => {}); // ignore internal logs
jest.spyOn(console, 'info').mockImplementation(() => {});
jest.spyOn(console, 'warn').mockImplementation(() => {});
});
describe('getUser', () => {
test.concurrent('should return an error if userId is empty or with a 400 statusCode', async () => {
const input = require('../../test-data/missing-user-id.json'); // input data from test-data folder
await getUserWorkplaces(input, undefined, (error, response: any) => {
expect(response.statusCode).toBe(400);
});
});
test.concurrent('should return success if the correct userId is provided', async () => {
const input = require('../../test-data/valid-user-id.json'); // input data from test-data folder
await getUserWorkplaces(input, undefined, (error, response: any) => {
expect(response.statusCode).toBe(200);
});
});
test.concurrent('should return an error if an invalid userId is provided with statusCode 404', async () => {
const input = require('../../test-data/valid-user-id.json'); // input data from test-data folder
await getUserWorkplaces(input, undefined, (error, response: any) => {
expect(response.statusCode).toBe(404);
});
});
});
Voilà, we have written our test cases and are good to go, just run :
npm run test
Automating Jest tests with AWS CodeBuild ensures robust testing before each release.
Prerequisites
Before getting started, make sure you have the following prerequisites in place:
In your project’s root directory, create a buildspec.yml file that defines the build steps, including installing dependencies and running Jest tests. Here's a basic example:
Assuming that your AWS CodeBuild release configuration is already established, emphasizing the execution of Jest tests within this pre-existing framework.
version: 0.2
phases:
install:
runtime-versions:
nodejs: 14
commands:
- npm install # Install project dependencies
pre_build:
commands:
- npm run test
build:
commands:
# Your Build scripts
This buildspec.yml file specifies that CodeBuild should use Node.js 14, install project dependencies using npm install, and run Jest tests with npm test.
You can expect to receive comprehensive test coverage reports as well as clear indications of passed and failed test cases when working with Jest.
It’s important to emphasize that while the code sample provided here demonstrates a basic setup, the Jest framework offers extensive customization options to tailor it to your specific needs.
We highly recommend referring to the Jest documentation for a more in-depth understanding of its configuration capabilities. This article serves as an illustration of Jest’s user-friendliness and its ability to streamline the process of writing and running test cases.
140L, 5th Main Rd, Sector 6, HSR Layout, Bengaluru, Karnataka 560102, India
+91 96418 61031
3500 S DuPont Hwy, Dover,
Kent 19901, Delaware, USA
+1 (341) 209-1116
3500 S DuPont Hwy, Dover,
Kent 19901, Delaware, USA
+1 (341) 209-1116
140L, 5th Main Rd, Sector 6, HSR Layout, Bengaluru, Karnataka 560102, India
+91 96418 61031