Getting Started with Jest — Install, Globals, and Expect Matchers
A consolidated walkthrough of Jest — setup, lifecycle hooks, `describe.each`, and the full matcher catalog (toBe, toEqual, arrayContaining, mock assertions, and more).
Consolidated from a 3-part Jest learning series written in June 2020. Vitest has since risen in the Vite ecosystem, but Jest remains standard in React.
What is Jest?
Jest is a JavaScript testing framework by Facebook, positioned as "Zero Config" — usable out of the box. It bundles the test runner, assertion library, mocking, and coverage reporting in a single package.
Since the React team included it in Create React App, Jest became the de facto standard for frontend unit testing.
Step 1 — Installation and First Test
npm install --save-dev jest
Add "test": "jest" to your package.json scripts. Create sum.js:
function sum(a, b) {
return a + b;
}
module.exports = sum;
And sum.test.js:
const sum = require('./sum');
test('1 + 2 = 3', () => {
expect(sum(1, 2)).toBe(3);
});
Running npm test auto-discovers .test.js files.
Step 2 — Globals for Test Structure
Jest provides globals available without imports in every test file.
Lifecycle Hooks
| Function | When |
|---|---|
beforeAll(fn) | Once, before all tests in the file |
afterAll(fn) | Once, after all tests in the file |
beforeEach(fn) | Before each test |
afterEach(fn) | After each test |
Useful for DB connections, fixture setup, etc.
Grouping Tests
describe('Calculator', () => {
test('add', () => {
/* ... */
});
test('subtract', () => {
/* ... */
});
});
Data-driven iteration with describe.each:
describe.each([
[1, 2, 3],
[2, 3, 5],
])('sum(%i, %i)', (a, b, expected) => {
test(`= ${expected}`, () => {
expect(sum(a, b)).toBe(expected);
});
});
Isolation & Focus
test.only— run only this testtest.skip— skip ittest.todo('...')— mark for later implementation
Step 3 — Expect Matchers
Assertions follow the pattern expect(actual).matcher(expected).
Value Comparison
| Matcher | Purpose |
|---|---|
.toBe(x) | Primitive equality (Object.is) |
.toEqual(x) | Deep structural comparison |
.toStrictEqual(x) | Stricter — includes undefined props and types |
.toBeNull() / .toBeUndefined() / .toBeDefined() | Specific values |
.toBeTruthy() / .toBeFalsy() | Boolean coercion |
.toBeGreaterThan(n) / .toBeLessThan(n) | Numeric |
.toBeCloseTo(n, digits) | Floating-point tolerance |
Array / Object Containment
| Matcher | Purpose |
|---|---|
.toContain(x) | Array includes item |
.toHaveLength(n) | Array/string length |
.toHaveProperty('a.b.c', v?) | Nested property existence/value |
expect.arrayContaining([...]) | Partial array matching |
expect.objectContaining({...}) | Partial object matching |
Mock Call Assertions
| Matcher | Purpose |
|---|---|
.toHaveBeenCalled() | Called at least once |
.toHaveBeenCalledTimes(n) | Exact call count |
.toHaveBeenCalledWith(...args) | Called with specific args |
.toHaveBeenLastCalledWith(...args) | Last-call args |
Error Assertions
expect(() => {
throwingFn();
}).toThrow('Expected message');
Retrospective
The first thing I loved about Jest was the zero-config experience. Compared to Mocha + Chai + Sinon, having runner, assertion, mocking, and coverage in one package lowered the adoption barrier significantly.
Limitations of the built-in jsdom and ongoing ESM compatibility are continually improving. Vitest has since entered the picture, but in the React ecosystem, Jest remains the standard choice.
Guestbook
Leave a short note about this post
Loading...