Performing NodeJS Unit testing using Jest
By Sandra Felice & Pawan Kumar, Community Contributors - May 2, 2023
NodeJS is a free, open-source, cross-platform runtime environment for executing JavaScript code outside the browser (mainly backend). It is often used to build backend services like APIs. It 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 improves the code quality and find bugs early 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 framework can be used for Unit Testing.
Benefits of Node.js Unit Testing
Node.js unit testing continues to provide many benefits in 2023, just as in previous years. Some of the critical benefits of Node.js unit testing include:
- Ensuring code quality: Unit testing helps ensure that code works as intended and meets quality standards. This is especially important in Node.js, often used for mission-critical applications.
- Fast and scalable: NodeJS is built on top of Google’s V8 JavaScript engine, which makes it very fast and efficient. It is also designed to be highly scalable, making it a popular choice for building large-scale, high-traffic applications.
- Cross-platform: It is a cross-platform environment, which means it can run on various operating systems, including Windows, macOS, and Linux..
- Enabling continuous integration and delivery: Unit testing can be integrated with CI/CD pipelines to ensure that code is tested automatically whenever it is changed. This helps catch errors and regressions quickly before they become production.
- Huge ecosystem: NodeJS has a vast and growing ecosystem of open-source libraries and frameworks that can be used to build a wide range of applications, from web servers to desktop applications.
- Improving maintainability: Unit tests serve as a form of documentation for the code, making it easier to understand and maintain over time.
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 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, several Jest Matchers assert certain conditions.
Types of Jest Matchers
Jest assertions use matches 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("Exact value 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 Assertion
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, and NaN are all examples of falsy concerning JavaScript.
test("truthiness Assertion", () => { var test="Software Testing demo" var n = null expect(n).toBeNull() expect(name).not.toBeNull // test should have a valid value expect(test).toBeTruthy() //fail - as null is unsuccess expect(n).toBeTruthy() // pass - null worked as false or negative expect(n).toBeFalsy() // 0 - work as false expect(0).toBeFalsy() })
Numeric Comparison Matchers
This is generally used for arithmetic operations such as greaterThan, lessThan, greaterThanOrEqual etc.
For Example:
test("numeric comparison", () => { var number1 = 100; var number2 = -20; var number3 = 0; // validate greater than expect(number1).toBeGreaterThan(10) // validate less than or equal expect(number2).toBeLessThanOrEqual(0) // validate greater than or equal expect(number3).toBeGreaterThanOrEqual(0) })
String Matchers
This provides matchers for strings to be matched against a regular expression.
For Example:
test("string matchers",() => { var string1 = "BrowserStack - Automation tool" // test for match the string - Success expect(string1).toMatch(/tool/); // test for not match the string - Failure 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 for NodeJS testing:
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 program’s source code 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 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" }, "keywords": [], "author": "", "license": "ISC", "dependencies": { "jest": "^29.7.0" } }
Creating a Simple NodeJS App
Once done with setting up unit testing Node js with Jest, 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:e:
const CalculationOperations = { Add: function(a,b) { return a + b; }, subtract: function(a,b) { return a - b; }, multiple: function(a,b) { return a * b; }, divide: function(a,b) { return a / b; } } module.exports = CalculationOperations
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 CalculationOperations = require('../src/calculator'); describe("Calculation TestCases", () => { test("Add 2 numbers", () => { //Call function of Add var sum = CalculationOperations.Add(1,2) // assertions expect(sum).toBe(3); }); test("Subtract 2 numbers", () => { //Call function of Subtract var subtract = CalculationOperations.subtract(10,2) // assertion expect(subtract).toBe(8); }); test("Multiple 2 numbers", () => { // Call function of Subtract var multiple = CalculationOperations.multiple(2,8) // assertion expect(multiple).toBe(16); }); test("Divide 2 numbers", () => { // Call function to divide the number var divide = CalculationOperations.divide(24,8) // assertion expect(divide).toBe(3); }); })
Now, let’s break our test on purpose. Update the calculator.test.js file to the following code snippet:
const CalculationOperations = require('../src/calculator'); describe("Calculation TestCases", () => { test("Add 2 numbers", () => { //Call function of Add var sum = CalculationOperations.Add(1,2) // assertions expect(sum).toBe(3); }); test("Subtract 2 numbers", () => { //Call function of Subtract var subtract = CalculationOperations.subtract(10,2) // assertion expect(subtract).toBe(21); //Update the value to failure purpose }); test("Multiple 2 numbers", () => { // Call function of Subtract var multiple = CalculationOperations.multiple(2,8) // assertion expect(multiple).toBe(10); //Update the value to failure purpose }); test("Divide 2 numbers", () => { // Call function to divide the number var divide = CalculationOperations.divide(24,8) // assertion expect(divide).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.
The quality of your NodeJS applications can be easily improved with Unit Testing since it helps find bugs and defects in your code. Moreover, the early discovery of Code bugs in the SDLC reduces the overall development cost because less time is spent on bug fixing in the later stage of the project.
- Once the unit testing is done, it is suggested to test the application end to end on real devices and browsers to identify 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 automation frameworks like Selenium, Cypress, Playwright, Puppeteer, etc. It is also compatible with CI/CD tools like Jenkins, Travis CI, CircleCI, Bamboo, etc.
- With the latest BrowserStack Test Observability, test reporting, precision debugging, flaky test detection and more are available on a single dashboard.
- File rich bug reports with relevant context, stack traces and more on Jira in a single click.