📘 ReactJS

Unit Testing — Jest / Vitest

Unit testing verifies small pieces of application logic in isolation. In a React application this commonly means testing utility functions, reducers, selectors, validation rules, hooks, and business logic without rendering the complete application. A strong test suite checks behavior rather than implementation details.

S

Site Administrator

📅 Sep 28, 2026 🕒 3 min read 👁 22 views
☆ Save 𝕏 in f ✆
Unit Testing — Jest / Vitest

Unit testing verifies small pieces of application logic in isolation. In a React application this commonly means testing utility functions, reducers, selectors, validation rules, hooks, and business logic without rendering the complete application. A strong test suite checks behavior rather than implementation details.

What should be unit tested?

Good unit-test candidates are deterministic functions with clear inputs and outputs. Examples include price calculations, permission checks, reducers, selectors, date formatting, validation rules, and business rules.

export function calculateTotal(items) {
  return items.reduce(
    (total, item) => total + item.price * item.quantity,
    0
  );
}

Jest example

import { describe, it, expect } from "@jest/globals";
import { calculateTotal } from "./cart";

describe("calculateTotal", () => {
  it("calculates the cart total", () => {
    const items = [
      { price: 100, quantity: 2 },
      { price: 50, quantity: 1 }
    ];

    expect(calculateTotal(items)).toBe(250);
  });
});

Vitest example

import { describe, it, expect } from "vitest";

describe("calculateTotal", () => {
  it("calculates total", () => {
    expect(calculateTotal([
      { price: 100, quantity: 2 },
      { price: 50, quantity: 1 }
    ])).toBe(250);
  });
});

Arrange, Act, Assert

A readable unit test normally prepares data, executes the behavior, and verifies the result.

// Arrange
const input = { price: 100, quantity: 3 };

// Act
const result = calculateLineTotal(input);

// Assert
expect(result).toBe(300);

Testing Redux reducers

const initialState = {
  items: []
};

it("adds a product", () => {
  const state = cartReducer(
    initialState,
    addItem({
      productId: 10,
      price: 100,
      quantity: 1
    })
  );

  expect(state.items).toHaveLength(1);
  expect(state.items[0].productId).toBe(10);
});

Mocking a dependency

Unit tests can replace a dependency with a controlled mock when the dependency is outside the behavior being tested.

const paymentService = {
  charge: vi.fn()
};

paymentService.charge.mockResolvedValue({
  transactionId: "TX100"
});

Good and bad unit tests

Good testProblematic test
Tests business behaviorTests private implementation details
Small and deterministicDepends on real network
FastDepends on timers and external services
Clear failure messageTests many unrelated behaviors

Complete output

Test Files  1 passed

Tests:
✓ calculates the cart total
✓ handles an empty cart
✓ adds a product to the reducer

Result:
3 passed, 0 failed

Common mistakes

  • Testing implementation details instead of observable behavior.
  • Making unit tests call real APIs.
  • Writing one enormous test for an entire feature.
  • Using mocks everywhere even when a real simple function is safer.
  • Ignoring edge cases such as empty arrays and invalid values.

Interview questions

  • What is a unit test?
  • Jest vs Vitest?
  • What should be mocked in a unit test?
  • What is Arrange-Act-Assert?
  • How would you test a Redux reducer?
  • Why should tests avoid implementation details?

Comments & Ratings (0)

Log in or create a student account to comment and rate this article.

Be the first to comment on this article.

Never miss a new post 📬

Get an email whenever a new article, project, cheatsheet or video drops.

✅

ℹ️