Skip to main content

JavaScript Testing Complete Guide 2026: Vitest, Jest, Testing Library

Published: March 7, 2026 Updated: May 8, 2026 Larry Qu 3 min read

Introduction

Modern JavaScript testing has evolved significantly. Vitest has emerged as a popular alternative to Jest, offering better performance and Vite integration.

This guide covers JavaScript testing in 2026.

Testing Tools Overview

Tool Type Performance Ecosystem
Vitest Test Runner Fast ⚡ Large
Jest Test Runner Medium Largest
Mocha Test Runner Medium Large
AVA Test Runner Fast Medium

Vitest

Setup

npm create vitest@latest my-app
cd my-app
npm install

Configuration

// vitest.config.js
import { defineConfig } from 'vitest/config';

export default defineConfig({
  test: {
    environment: 'node',
    globals: true,
    coverage: {
      provider: 'v8',
      reporter: ['text', 'json', 'html'],
    },
  },
});

Writing Tests

import { describe, it, expect, beforeEach } from 'vitest';

describe('Math utilities', () => {
  beforeEach(() => {
    // Setup
  });

  it('adds two numbers', () => {
    expect(2 + 2).toBe(4);
  });

  it('handles arrays', () => {
    const arr = [1, 2, 3];
    expect(arr).toHaveLength(3);
    expect(arr).toContain(2);
  });

  it('async operation', async () => {
    const data = await fetchData();
    expect(data).toBeDefined();
  });
});

Mocking

import { vi, expect, it } from 'vitest';

vi.mock('./api', () => ({
  fetchUser: () => Promise.resolve({ id: 1, name: 'John' }),
}));

it('mocks API', async () => {
  const user = await fetchUser();
  expect(user.name).toBe('John');
});

Jest

Setup

npm install --save-dev jest

Configuration

// jest.config.js
module.exports = {
  testEnvironment: 'node',
  coverageDirectory: 'coverage',
  collectCoverageFrom: [
    'src/**/*.js',
    '!src/**/*.test.js',
  ],
};

Writing Tests

describe('String utilities', () => {
  test('reverses string', () => {
    expect(reverse('hello')).toBe('olleh');
  });

  test('capitalizes', () => {
    expect(capitalize('hello')).toBe('Hello');
  });
});

Testing Library

Installation

npm install --save-dev @testing-library/react @testing-library/dom

Query Methods

import { render, screen, fireEvent } from '@testing-library/react';
import { Button } from './Button';

test('button click', () => {
  const handleClick = vi.fn();
  render(<Button onClick={handleClick}>Click me</Button>);
  
  fireEvent.click(screen.getByText('Click me'));
  
  expect(handleClick).toHaveBeenCalledTimes(1);
});

Common Queries

// Get by text
screen.getByText('Submit');

// Get by role
screen.getByRole('button', { name: /submit/i });

// Get by testid
screen.getByTestId('submit-button');

// Query vs Get (throw vs return null)
screen.getByText('Submit');     // Throws if not found
screen.queryByText('Submit');   // Returns null if not found

Best Practices

Test Structure

describe('Component', () => {
  // Setup
  beforeEach(() => { ... });
  
  // Tests
  it('should do something', () => { ... });
  
  // Teardown
  afterEach(() => { ... });
});

Naming Conventions

// Good naming
it('should return 404 when user not found');
it('should throw error for invalid input');

// Bad naming
it('test1');
it('works');

AAA Pattern

it('calculates total correctly', () => {
  // Arrange
  const cart = [{ price: 10 }, { price: 20 }];
  
  // Act
  const total = calculateTotal(cart);
  
  // Assert
  expect(total).toBe(30);
});

Conclusion

Modern JavaScript testing is powerful and fast. Use Vitest for new projects, Testing Library for component tests, and follow AAA pattern.

Resources

Comments

👍 Was this article helpful?