← DEVLOG
Tech Notes2020.06.235 min read

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).

jestunit-testjavascripttesting

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

FunctionWhen
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 test
  • test.skip — skip it
  • test.todo('...') — mark for later implementation

Step 3 — Expect Matchers

Assertions follow the pattern expect(actual).matcher(expected).

Value Comparison

MatcherPurpose
.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

MatcherPurpose
.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

MatcherPurpose
.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

0 / 140

Loading...