Unit testing for NodeJS using Jest Framework: Tutorial
By Sandra Felice, Community Contributor - May 23, 2022
NodeJS is a free, open-source, and cross-platform runtime environment for executing JavaScript code outside of the browser (mainly backend). It is often used to build backend services like APIs and is ideal for developing highly-scalable, data-intensive, and real-time applications since it has the largest ecosystem of open-source libraries available. It is a popular tool for almost any kind of project.
What is NodeJS Unit testing?
Test-driven development is a powerful tool for preventing bugs within your application. NodeJS Unit testing is the method of testing small pieces of code/components in isolation in your NodeJS application. This helps in improving the code quality and helps in finding bugs early on in the development life cycle. This also provides an added advantage to the users in the way that they can add any new features without breaking any other part of their application.
For your NodeJS applications, Jest can be used for Unit Testing.
What is Jest Framework?
Jest is an open-source Javascript testing framework developed by Facebook. It was mainly built for React, Node, Babel, TypeScript, Angular, Vue, and JavaScript-based applications. It primarily focuses on simplicity and support for large web applications. Jest was built on top of Jasmine with multiple layers.
Features of Jest Framework:
- Zero configuration setup – One doesn’t need to do a lot of setup in terms of configuration while working with jest
- Extremely fast – Tests run in parallel in their own sandbox
- Provides built-in code coverage support
- Provides out of box support for mocks – You can mock entire API responses or entire node module etc.
- Supports snapshot testing
Jest uses BDD-style tests. Each test suite has one main describe block and can have multiple test blocks. These test blocks can have nested describe blocks as well.
Read More: BDD vs TDD vs ATDD: Key Differences
There are three main methods in this test file:
- describe() – It is a suite of Test scripts that gives an outer description for the test suite
- test() – It is the smallest unit test case that is written to be executed. String in quotes represents the test name
- expect() – It is an assertion. Every test() statement has an expect() function which takes a value and expects a return in true form.
Apart from the above methods, we have several Jest Matchers which assert on certain conditions.
Types of Jest Matchers
Jest assertions use matchers to assert on a condition in different ways. Jest uses matchers from the expect API. For the full list, see the Expect API doc.
Let’s walk through some of the most commonly used matchers along with Jest tests:
Equality
This is the most commonly used matcher. This is used for arithmetic operations and for checking equality or inequality.
For Example
test("equality matchers", () => { expect(2*2).toBe(4); expect(4-2).not.toBe(1); })
toBe and not.toBe are analogous to equals and not equals respectively.
Truthiness
This is used for null, falsy and truthy i.e. false and true values. Anything that is not logically true is falsy. number 0, null, empty string, NaN are all examples of falsy concerning JavaScript.
test("truthy operators", () => { var name="Software testing help" var n = null expect(n).toBeNull() expect(name).not.toBeNull // name has a valid value expect(name).toBeTruthy() //fail - as null is non success expect(n).toBeTruthy() // pass - null treated as false or negative expect(n).toBeFalsy() // 0 - treated as false expect(0).toBeFalsy() })
Number Matchers
This is generally used for arithmetic operations such as greaterThan, lessThan, greaterThanOrEqual etc.
For Example:
test("numeric operators", () => { var num1 = 100; var num2 = -20; var num3 = 0; // greater than expect(num1).toBeGreaterThan(10) // less than or equal expect(num2).toBeLessThanOrEqual(0) // greater than or equal expect(num3).toBeGreaterThanOrEqual(0) })
String Matchers
This provides matchers for strings to be matched against a regular expression.
For Example:
test("string matchers",() => { var string1 = "software testing help - a great resource for testers" // test for success match expect(string1).toMatch(/test/); // test for failure match expect(string1).not.toMatch(/abc/) })
How to Install and Set up Jest for NodeJS Unit Testing?
Follow the steps below to install and set up Jest:
Step 1: Create a new directory for your project file:
mkdir JestApp
Step 2: Go to the new directory and execute the below command to initialize a project with Default configurations:
cd JestApp npm init --y
Step 3: The above step creates a package.json file. Launch this project in any of the source-code editors (Using VS Code in my case)
Step 4: Create two folders named src and test respectively. src stores the main file where the source code of the program is written. test is where test cases for unit testing are stored.
Step 5: Create a calculator.js file under the src folder and calculator.test.js file under the test folder (as shown in the screenshot above)
Step 6: Open the package.json file and change the “scripts” block to “jest” using the below code
{ "name": "jest", "version": "1.0.0", "description": "", "main": "index.js", "scripts": { "test": "jest" }, "keywords": [], "author": "", "license": "ISC", } }
Step 7: In the terminal, type the following for installing Jest:
npm install -- save-dev jest
The package.json file will look like this once Jest is installed. You could also add an additional configuration in the package.json file to see the code coverage report of your test cases later.
{ "name": "jest", "version": "1.0.0", "description": "", "main": "index.js", "scripts": { "test": "jest" }, "jest": { "collectCoverage":true }, "keywords": [], "author": "", "license": "ISC", "dependencies": { "jest": "^28.1.0" } }
Creating a Simple NodeJS App
Let us start by creating a Simple NodeJS application that performs addition, subtraction, multiplication, and division of two numbers just like a calculator.
For the source code, enter the following snippet under the calculator.js file:
const mathOperations = { sum: function(a,b) { return a + b; }, diff: function(a,b) { return a - b; }, product: function(a,b) { return a * b; }, divide: function(a,b) { return a / b; } } module.exports = mathOperations
Read More: Unit Testing Frameworks in Selenium
Run NodeJS Unit Test using Jest: Example
For the test cases, enter the following snippet under the calculator.test.js file:
const mathOperations = require('../src/calculator'); describe("Calculator Tests", () => { test("Addition of 2 numbers", () => { // arrange and act var result = mathOperations.sum(1,2) // assert expect(result).toBe(3); }); test("Subtraction of 2 numbers", () => { // arrange and act var result = mathOperations.diff(10,2) // assert expect(result).toBe(8); }); test("Multiplication of 2 numbers", () => { // arrange and act var result = mathOperations.product(2,8) // assert expect(result).toBe(16); }); test("Division of 2 numbers", () => { // arrange and act var result = mathOperations.divide(24,8) // assert expect(result).toBe(3); }); })
Now, let’s run the above test file using the command:
npm run test
Test Result
A successful result will look something like this:
Now, let’s break our test on purpose. Update the calculator.test.js file to the following code snippet:
const mathOperations = require('../src/calculator'); describe("Calculator Tests", () => { test("Addition of 2 numbers", () => { // arrange and act var result = mathOperations.sum(1,2) // assert expect(result).toBe(3); }); test("Subtraction of 2 numbers", () => { // arrange and act var result = mathOperations.diff(10,2) // assert expect(result).toBe(21); //updated to fail }); test("Multiplication of 2 numbers", () => { // arrange and act var result = mathOperations.product(2,8) // assert expect(result).toBe(10); //updated to fail }); test("Division of 2 numbers", () => { // arrange and act var result = mathOperations.divide(24,8) // assert expect(result).toBe(3); }); })
The second and third tests were updated to throw an error. Rerun the test using the below command
npm run test
A failed result will look something like this:
Similarly, multiple Unit test cases can be written for your NodeJS application using Jest.
Read More: Best Practices for Unit Testing
The quality of your NodeJS applications can be easily improved with Unit Testing since it helps in finding bugs and defects in your code. Moreover, the early discovery of Code bugs in the SDLC reduces the overall cost of development because less time is spent on bug fixing in the later stage of the project. Due to this, the overall customer satisfaction has increased and it has helped in gaining more trustworthy clients.
Once, the unit testing is done, it is suggested to test the application end to end on real devices and browsers for identifying bottlenecks in the user experience. Using a real device cloud, like BrowserStack, allows you to test on 3000+ browser device combinations, under real user conditions.
BrowserStack is compatible with different automation frameworks like Selenium, Cypress, Playwright, Puppeteer, etc. It is also compatible with CI/CD tools like Jenkins, Travis CI, CircleCI, Bamboo, etc. facilitating Agile Teams to test on real browsers and devices, thus accelerating the software development cycle. It also supports parallel testing, which helps save time by running tests on multiple browsers and devices simultaneously.