Frontend Development 14 min read

Introduction to Front-End Unit Testing with Jest

This guide introduces front‑end unit testing with Jest, explaining TDD and BDD concepts, installation, writing simple and ES6/TypeScript tests, configuring coverage, using common matchers, and employing mock functions, timers, and module mocking to ensure reliable, maintainable code.

HelloTech
HelloTech
HelloTech
Introduction to Front-End Unit Testing with Jest

Front‑end unit testing refers to testing the smallest testable units of front‑end code, such as functions, components or modules. By writing test cases for these units, developers can verify that the code behaves as expected under various conditions.

The two main development approaches mentioned are:

TDD (Test‑Driven Development): write tests before the actual code.

BDD (Behavior‑Driven Development): focus on the behavior of the system.

Benefits of unit testing include higher code quality, easier debugging, safe refactoring, and better team collaboration.

How to perform unit testing with Jest

1. Install Jest using your preferred package manager:

npm install --save-dev jest

2. Create a simple demo module sum.js :

function sum(a, b) {
  return a + b;
}
module.exports = sum;

3. Write test cases in sum.test.js :

const sum = require('./sum');

describe('sum.js', () => {
  test('adds two numbers', () => {
    expect(sum(1, 2)).toBe(3);
  });
  it('concatenates strings', () => {
    expect(sum('a', 'b')).toBe('ab');
  });
});

4. Add a test script to package.json :

{
  "scripts": {
    "test": "jest"
  }
}

5. Run the tests:

npm run test

If everything is set up correctly, Jest will output a summary of passed tests.

Supporting ES6 syntax

Jest runs in a Node environment using CommonJS. To use ES6 import/export , install Babel:

npm install --save-dev @babel/core @babel/preset-env

Create a .babelrc file:

{
  "presets": ["@babel/preset-env"]
}

Now you can write modules with ES6 syntax:

export function sum(a, b) {
  return a + b;
}
import { sum } from './sum';

describe('sum.js', () => {
  test('adds two numbers', () => {
    expect(sum(1, 2)).toBe(3);
  });
  test('concatenates strings', () => {
    expect(sum('a', 'b')).toBe('ab');
  });
});

Using TypeScript

Install the TypeScript preset for Babel and the Jest type definitions:

npm install --save-dev @babel/preset-typescript
npm install --save-dev @types/jest

Update .babelrc :

{
  "presets": ["@babel/preset-env", "@babel/preset-typescript"]
}

Test coverage configuration

module.exports = {
  collectCoverage: true,
  collectCoverageFrom: ['src/utils/**/*'],
  extensionsToTreatAsEsm: ['.tsx', '.jsx', '.ts'],
  coverageThreshold: {
    global: {
      statements: 90,
      functions: 90,
      branches: 60
    }
  }
};

Common matchers

Jest provides many assertion helpers:

test('equality', () => {
  const foo = { bar: 1 };
  expect(foo.bar).toBe(1); // passes
  expect(foo).toEqual({ bar: 1 }); // passes
});

test('not', () => {
  const foo = 1;
  expect(foo).not.toBe(2);
});

test('match', () => {
  const foo = 'hello jest';
  expect(foo).toMatch(/hello/i);
});

test('contain', () => {
  const data = ['foo', 'bar'];
  expect(data).toContain('foo');
});

Other matchers include toBeNull , toBeUndefined , toBeTruthy , toBeFalsy , toBeGreaterThan , toBeLessThanOrEqual , toBeCloseTo , etc.

Mock functions

// create a mock function
const func = jest.fn();
func.mockReturnValue(1);
func.mockReturnValueOnce(2);
func.mockImplementation(params => {
  console.log('func called with', params);
});
func.mockImplementationOnce(() => {});
console.log(func.mock.calls.length); // call count
console.log(func.mock.calls[0]); // arguments of first call
console.log(func.mock.instances[0]); // this of first call

Mock timers

function handleData(callback) {
  setTimeout(() => {
    callback('bar');
    setTimeout(() => {
      callback('foo');
    }, 1000);
  }, 30 * 1000);
}

beforeEach(() => {
  jest.useFakeTimers();
});

describe('test mock timer', () => {
  test('runAllTimers', () => {
    const fn = jest.fn();
    handleData(fn);
    jest.runAllTimers();
    expect(fn.mock.calls.length).toBe(2);
    expect(fn.mock.calls).toEqual(['bar', 'foo']);
  });
});

Mocking modules

// mock a module
jest.mock('./service', () => {
  const actualModules = jest.requireActual('./service');
  return {
    ...actualModules,
    fetchData1: jest.fn(() => Promise.resolve({ foo: 'bar' }))
  };
});

import { fetchData1, fetchData2 } from './service';

describe('test mock modules', () => {
  test('fetchData1', async () => {
    const res = await fetchData1();
    expect(res).toEqual({ foo: 'bar' });
  });
  test('fetchData2', async () => {
    const res = await fetchData2();
    expect(res).toEqual({ type: '5G' });
  });
});

The article concludes with a reminder to click “The End” and a short promotional note, which is not part of the technical content.

javascriptfrontendunit testingmockingJestTDD
HelloTech
Written by

HelloTech

Official Hello technology account, sharing tech insights and developments.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.