Writing code is fun, but debugging is painful! Jest helps us catch bugs early and ensures our JavaScript code works correctly.
In this post, I am going to explain how i understood Jest in a most easiest way possible for testing back end apis.
By the end of this post, you’ll understand how to use Jest to test your JavaScript code, APIs, and more—without pulling your hair out!
Table of Contents
- Why Do We Need Jest?
- Installing Jest
- Writing Your First Test
- Matchers in Jest
- Testing APIs with Jest
- Testing Asynchronous Code
- Mocking Functions
- Real-World Example: Testing a Product Management System
- Conclusion
The first question that came to my mind was -
Why Do We Need Jest? Can’t We Just Test APIs by Running Them?
_
Jest is like a robot helper for programmers
. Imagine you’re building a cool app, like a game or a website. You want to make sure everything works perfectly before you show it to your friends. But checking every single part of your app by hand would take forever! That’s where Jest comes in.
Jest is a tool that automatically tests your code to make sure it does what it’s supposed to do. It’s like having a robot that plays with your app, clicks buttons, and checks if everything works correctly._
-
It’s Faster
Imagine you have 100 buttons in your app. Testing each one by hand would take hours. Jest can test all of them in seconds!
Jest runs all your tests automatically, so you don’t have to click around or type commands over and over.
-
It’s Smarter
Jest can test every little detail of your code. For example:
Does this function return the right number? Does this API return the correct data? What happens if someone tries to break your app by sending weird inputs?
Jest can handle all these scenarios without you lifting a finger.
-
It Catches Mistakes
Sometimes, when you change your code, you accidentally break something. Jest helps you catch these mistakes before they become big problems.
For example, if you change a function and it stops working, Jest will tell you right away.
-
It Works for Everything
Jest isn’t just for APIs. It can test:
Functions (like math calculations) Components (like buttons or menus in a website) APIs (like the ones that fetch data from a server)
It’s like a Swiss Army knife for testing!
-
It’s Fun!
Writing tests with Jest is like solving puzzles. You write little challenges for your code, and Jest checks if your code can solve them.
It’s also super satisfying when all your tests pass and you know your app is working perfectly.
🔹 Installing Jest
npm install --save-dev jest
The keywords in JEST can be easily understandable as they have the exact literal meaning as its supposed to.
Writing Your First Test
Let's say you have a function sum.js that you want to test:
function sum(a, b) {
return a + b;
}
module.exports = sum;
You can write a test for this function by creating a file named sum.test.js:
const sum = require('./sum');
test('adds 1 + 2 to equal 3', () => {
expect(sum(1, 2)).toBe(3);
});
Running Your Tests
Add the following section to your package.json:
{
"scripts": {
"test": "jest"
}
}
Then, you can run your tests using:
npm test or npm run test.
Matchers in Jest
Jest uses "matchers" to let you test values in different ways. The most common matchers are:
toBe uses Object.is to test exact equality.
toEqual recursively checks every field of an object or array.
toBeNull matches only null.
toBeUndefined matches only undefined.
toBeDefined is the opposite of toBeUndefined.
toBeTruthy matches anything that an if statement treats as true.
toBeFalsy matches anything that an if statement treats as false.
Testing APIs with Jest
📝 Example: API Testing Without Jest vs. With Jest
Imagine building a vending machine that sells snacks. You want to make sure it works perfectly before customers start using it. But manually testing every button and snack combination would take forever. Enter Jest—your robot helper for testing!
❌ Manually Testing an API (Like Pressing Buttons Yourself)
1.Open Postman or a browser.
2.Make a request: GET /snacks/1
3.Check if you get: { "id": 1, "name": "Chips", "price": 10 }
Repeat for every snack/api endpoints in your database. 😫
✅ Jest Testing the API (Like a Robot Checking Everything for You):
const { app } = require('../index');
test('GET /snacks/:id should return the correct snack', async () => {
const response = await request(app).get('/snacks/1');
expect(response.status).toBe(200);
expect(response.body).toEqual({ id: 1, name: "Chips", price: 10 });
});
Testing Asynchronous Code
Jest has several ways to handle asynchronous code:
Promises
Return a promise from your test, and Jest will wait for that promise to resolve:
test('the data is peanut butter', () => {
return fetchData().then(data => {
expect(data).toBe('peanut butter');
});
});
Async/Await
Or you can use async and await in your tests:
test('the data is peanut butter', async () => {
const data = await fetchData();
expect(data).toBe('peanut butter');
});
Mocking Functions
Jest can mock functions to isolate them from actual API calls or external dependencies.
const fetchData = jest.fn(() => "Mocked Data");
test('mock function test', () => {
expect(fetchData()).toBe("Mocked Data");
expect(fetchData).toHaveBeenCalledTimes(1);
});
Now, here it gets interesting..
Lets understand with an example.
Real-World Example: Testing a Product Management System
🛍️** Testing Product Management with Jest**
Imagine you're building an online store, and you have a list of products like Laptops, Coffee Makers, and Shoes. You want to test if:
✅ Your store returns all available products.
✅ You can fetch a product using its ID.
✅ The function returns undefined if a product doesn't exist.
✅ You can add a new product, and the total count increases.
1️⃣ Checking All Products
This test verifies that four products exist in the store initially.
It compares the actual product list with an expected array.
2️⃣ Getting a Product by ID
It tests if ID 1 returns a Laptop from the store.
3️⃣ Handling Non-Existent Products
It checks if an invalid ID 99 correctly returns undefined.
4️⃣ Adding a New Product
It adds a new Tablet to the store.
The test ensures the new product has an ID (5) and the total product count increases.
🖼️ Illustration: How the Test Works
here's the code representation of this concept -
getProducts()
→ Retrieves all products.
getProductById(id)
→ Fetches a specific product by its id.
addProduct(product)
→ Adds a new product to the list.
These functions are already defined in Product.js file.
let products = [
{ id: 1, name: 'Laptop', category: 'Electronics' },
{ id: 2, name: 'Coffee Maker', category: 'Appliances' },
{ id: 3, name: 'Headphones', category: 'Electronics' },
{ id: 4, name: 'Running Shoes', category: 'Footwear' },
];
function getProducts() {
return products;
}
function getProductById(id) {
return products.find(product => product.id === id);
}
function addProduct(product) {
const newProduct = { id: products.length + 1, ...product };
products.push(newProduct);
return newProduct;
}
module.exports = { getProducts, getProductById, addProduct };
products.test.js
const { getProducts, getProductById, addProduct } = require('../product');
describe('Products Functions', () => {
// All tests related to products go inside the describe block.
it('should return all products', () => {
//Each it() function represents a single test case.
let products = getProducts();
console.log('Initial Products:', products);
expect(products.length).toEqual(4);
//expect() is used to compare actual vs expected results.
expect(products).toEqual([
{ id: 1, name: 'Laptop', category: 'Electronics' },
{ id: 2, name: 'Coffee Maker', category: 'Appliances' },
{ id: 3, name: 'Headphones', category: 'Electronics' },
{ id: 4, name: 'Running Shoes', category: 'Footwear' },
]);
});
it('should return a product by id', () => {
let product = getProductById(1);
console.log('Product Retrieved:', product);
expect(product).toEqual({
id: 1,
name: 'Laptop',
category: 'Electronics',
});
});
it('should return undefined for non-existent product', () => {
let product = getProductById(99);
console.log('Non-existent Product:', product);
expect(product).toBeUndefined();
//getProductById(99) is called, but product ID 99 does not exist.
});
it('should add a new Product', () => {
let newProduct = { name: 'Tablet', category: 'Electronics' };
let addedProduct = addProduct(newProduct);
console.log('Product Added:', addedProduct);
expect(addedProduct).toEqual({
id: 5,
name: 'Tablet',
category: 'Electronics',
});
let products = getProducts();
console.log('Updated Products:', products);
expect(products.length).toEqual(5);
});
});
Without Jest, you would have to manually:
Run `getProducts()`, check if the output is correct.
Call `getProductById(1)`, manually verify if it returns the correct product.
Add a product, then check the list manually.
🔥 Jest automates all of this, runs the tests, and gives clear results showing which tests passed or failed!
running npm run test
will give
You didn't understand or if u skipped the code. Just read the code like a paragraph. its that easy.
Common Jest Errors:
Even with Jest, you may run into errors while testing. Here are a few common ones and their solutions:
1️⃣ TypeError: Cannot read properties of undefined (reading 'xyz')
🔍 Cause: You're trying to access a property of an undefined object.
🔍 Cause: Your test expectation doesn't match the actual output.
🔍 Cause: Your test contains an unresolved async operation (e.g., missing await).
🔍 Cause: Your test expects a function to be called, but it's not.
✅ Fix:
Ensure your function handles missing data properly, or check if mock data is initialized correctly.Print the actual output using console.log() before expect() to debug the issue.
Conclusion
Testing your code doesn’t have to be a chore—it can actually be fun and rewarding! With Jest, you can automate the tedious parts of testing, catch bugs early, and ensure your code works exactly as expected. Whether you’re testing simple functions, complex APIs, or even entire applications, Jest is your trusty robot helper that makes the process fast, reliable, and even enjoyable.
⬆️ Back to Top
To continue with Mock functions, tune to part 2 >>>
Top comments (0)