Explore the importance of Unit Testing in JavaScript using Jest and Mocha. Improve your code quality with beginner and advanced test case examples.
You wrote the function. It works on your machine. Three weeks later someone refactors it, ships, and it quietly breaks in production. That gap, between “it worked when I wrote it” and “it still works now,” is exactly what unit tests close.
Welcome to Day 15 of our 30 Days of JavaScript series. Today is about unit testing: checking the small, individual pieces of your code, the “units,” in isolation so you know each one still does what you think it does.
We’ll cover why it’s worth your time, look at Jest and Mocha (the two frameworks most JavaScript developers actually reach for), and write real tests from a one-line function up to a mocked API call. Do this well and you catch bugs early, refactor without fear, and trust your own code again.
Table of Contents
- Why bother testing?
- Jest and Mocha: the two you’ll actually use
- Writing and running your first tests
- Going further: mocking and friends
- The takeaway
Why bother testing?
A unit test is a small check that one piece of your code behaves the way you claim it does. That sounds modest, but it pays off in a few concrete ways:
- You catch bugs early: a failing test tells you at commit time, not after a user finds it.
- You debug faster: when a test breaks, it points at the exact unit that’s wrong, so you’re not guessing.
- You can change things safely: refactor or add a feature, run the tests, and know in seconds whether you broke anything.
- Your team can trust the code: tests double as living documentation of what each function is supposed to do.
Jest and Mocha: the two you’ll actually use
Two frameworks dominate JavaScript unit testing: Jest and Mocha. They take different philosophies, so it’s worth seeing both before you pick.
Jest
Jest started life at Facebook and now lives under the OpenJS Foundation, where the community maintains it. Its whole pitch is simplicity: install it and it works out of the box with almost no config. You get snapshot testing and parallel test runs without wiring anything up yourself.
- Zero configuration: for most projects it runs the moment you install it.
- Snapshot testing: saves a snapshot of a rendered component or any serializable value, then flags you when it changes.
- Parallel test running: runs your test files in parallel so big suites finish faster.
Getting started with Jest
Install Jest as a dev dependency with npm:
npm install --save-dev jestHere’s a simple test written with Jest:
/**
* Simple test to check if 1 + 2 equals 3.
*
* @returns {void}
*/
test('adds 1 + 2 to equal 3', () => {
expect(1 + 2).toBe(3);
});Run it with:
npm run testMocha
Mocha takes the opposite approach. It hands you the test structure (describe, it, and hooks) and stays out of your way on everything else. You bring your own assertion library, and most people pair Mocha with Chai.
- Flexible and modular: choose the assertion style you like, such as Chai.
- Async support: handles promises and async/await cleanly.
- Rich plugin ecosystem: extend it with plugins and custom reporters.
Getting started with Mocha
Install Mocha as a dev dependency:
npm install --save-dev mochaHere’s the same idea written with Mocha and the built-in assert module:
/**
* Basic test using Mocha and the assert library.
*
* @returns {void}
*/
var assert = require('assert');
describe('Simple Test', function() {
it('should return -1 when the value is not present', function() {
assert.equal([1, 2, 3].indexOf(4), -1);
});
});Run the tests with:
npm run testWriting and running your first tests
A test case is just a scenario: given this input, I expect that output. Let’s build a couple, starting simple and adding a little complexity.
Beginner: testing a pure function
Start with a function that adds two numbers:
/**
* Function to add two numbers.
*
* @param {number} a - First number.
* @param {number} b - Second number.
* @returns {number} The sum of a and b.
*/
function add(a, b) {
return a + b;
}Now test it with Jest:
/**
* Test case for add function to check if 3 + 7 equals 10.
*
* @returns {void}
*/
test('adds 3 + 7 to equal 10', () => {
expect(add(3, 7)).toBe(10);
});A step up: testing array logic
Here’s a slightly busier function that strips the negative numbers out of an array:
/**
* Function to filter negative numbers from an array.
*
* @param {Array<number>} numbers - The array of numbers.
* @returns {Array<number>} The filtered array with non-negative numbers.
*/
function filterNegative(numbers) {
return numbers.filter(number => number >= 0);
}Test it with Mocha and Chai:
/**
* Mocha test case for filterNegative function.
*
* @returns {void}
*/
var expect = require('chai').expect;
describe('Filter Negative Numbers', function() {
it('should filter out negative numbers', function() {
var numbers = [-1, 2, -3, 4];
var result = filterNegative(numbers);
expect(result).to.eql([2, 4]);
});
});Going further: mocking and friends
Real code isn’t all pure functions. It calls APIs, hits databases, and waits on promises. To test a unit in isolation, you fake the messy parts around it. That’s what mocking, spying, and stubbing are for: they let you test behavior without the network or a real backend in the loop.
Mocking a function with Jest
Here’s a small example of mocking with Jest:
/**
* Mocking fetchData function in Jest.
*
* @returns {void}
*/
jest.mock('fetchData');
test('fetches data', () => {
const data = 'some data';
fetchData.mockResolvedValueOnce(data);
expect(fetchData()).resolves.toBe(data);
});
Here Jest stands in for fetchData so you control exactly what it returns. Your test never touches the real API, which means it runs fast and it won’t fail just because the network had a bad day.
The takeaway
That’s Day 15. We started with why unit testing earns its place, met Jest and Mocha and their different philosophies, and wrote tests from a one-line add function up to a mocked API call.
None of this is about chasing a perfect coverage number. It’s about trust. When your tests are green, you can refactor, add features, and hand the code to a teammate without holding your breath.
Testing is more habit than skill. Write a few, feel the moment a test catches a bug before your users do, and you’ll keep writing them.
What’s Next?
Day 16 is Web Components and Custom Elements. We’ll build reusable, encapsulated components using the browser’s own APIs, no framework required, so the same component drops into React, Vue, or plain HTML. See you there.


