HeoLab
ToolsBlogAboutContact
HeoLab

Free developer tools with AI enhancement. Built for developers who ship.

Tools

  • JSON Formatter
  • JWT Decoder
  • Base64 Encoder
  • Timestamp Converter
  • Regex Tester
  • All Tools →

Resources

  • Blog
  • What is JSON?
  • JWT Deep Dive
  • Base64 Explained

Company

  • About
  • Contact
  • Privacy Policy
  • Terms of Service

© 2026 HeoLab. All rights reserved.

Tools work in your browser. Zero data retention.

HomeBlogUnit Testing Best Practices in JavaScript
Table of Contents▾
  • Table of Contents
  • The AAA Pattern
  • What to Test (and What Not To)
  • Writing Descriptive Test Names
  • Mocking and Stubs
  • Testing Async Code
  • Code Coverage: The Right Mindset
  • Jest coverage report
  • Set minimum thresholds in jest.config.js
tutorials#testing#javascript#jest

Unit Testing Best Practices in JavaScript

How to write meaningful unit tests — the AAA pattern, what to test, mocking strategies, and coverage that actually matters.

Trong Ngo
February 26, 2026
3 min read

Table of Contents

  • The AAA Pattern
  • What to Test (and What Not To)
  • Writing Descriptive Test Names
  • Mocking and Stubs
  • Testing Async Code
  • Code Coverage: The Right Mindset

The AAA Pattern

Every good unit test follows Arrange → Act → Assert:

import { calculateTax } from './tax';

test('calculateTax returns 10% of the amount', () => {
  // Arrange
  const amount = 100;
  const rate = 0.1;

  // Act
  const result = calculateTax(amount, rate);

  // Assert
  expect(result).toBe(10);
});

What to Test (and What Not To)

Test:

  • Business logic and calculations
  • Edge cases (empty arrays, null values, boundaries)
  • Error handling and thrown exceptions
  • Public API of your functions/classes

Don't test:

  • Implementation details (private methods, internal state)
  • Third-party libraries (trust they're tested)
  • Simple getters/setters with no logic

Writing Descriptive Test Names

// Bad — what does 'works' mean?
test('calculateTax works', () => { ... });

// Good — describes input and expected output
test('calculateTax returns 0 when amount is 0', () => { ... });
test('calculateTax throws when rate is negative', () => { ... });

// Pattern: 'should [do X] when [condition Y]'
describe('UserService', () => {
  describe('createUser', () => {
    it('should return the created user with an id', async () => { ... });
    it('should throw ValidationError when email is missing', async () => { ... });
  });
});

Mocking and Stubs

import { sendWelcomeEmail } from './emailService';
jest.mock('./emailService');

test('createUser sends a welcome email', async () => {
  const mockSend = sendWelcomeEmail.mockResolvedValueOnce(true);

  await createUser({ name: 'Trong', email: 'trong@test.com' });

  expect(mockSend).toHaveBeenCalledTimes(1);
  expect(mockSend).toHaveBeenCalledWith(expect.objectContaining({
    email: 'trong@test.com'
  }));
});

Testing Async Code

// Return promise or use async/await
test('fetchUser returns user data', async () => {
  const user = await fetchUser(1);
  expect(user.id).toBe(1);
  expect(user.name).toBeDefined();
});

// Testing rejections
test('fetchUser throws on 404', async () => {
  await expect(fetchUser(9999)).rejects.toThrow('User not found');
});

Code Coverage: The Right Mindset

100% coverage is a vanity metric. A test that calls every line without asserting anything is useless.

Aim for:

  • High coverage on business-critical code (payment, auth, data processing)
  • Every bug fix accompanied by a regression test
  • Edge cases explicitly tested, not just the happy path
# Jest coverage report
jest --coverage

# Set minimum thresholds in jest.config.js
coverageThreshold: {
  global: { branches: 80, functions: 85, lines: 85 }
}

Related Articles

Web Performance Optimization: A Practical Developer's Guide

3 min read

TypeScript Advanced Types You Should Know

3 min read

REST API Design Best Practices: A Complete Guide

2 min read

Back to Blog

Table of Contents

  • Table of Contents
  • The AAA Pattern
  • What to Test (and What Not To)
  • Writing Descriptive Test Names
  • Mocking and Stubs
  • Testing Async Code
  • Code Coverage: The Right Mindset
  • Jest coverage report
  • Set minimum thresholds in jest.config.js

Related Articles

Web Performance Optimization: A Practical Developer's Guide

3 min read

TypeScript Advanced Types You Should Know

3 min read

REST API Design Best Practices: A Complete Guide

2 min read