Тестирование TypeScript: пошаговое руководство для новичков

Онлайн-тренажер Python для начинающих

Изучайте Python легко и без перегрузки теорией. Решайте практические задачи с автоматической проверкой, получайте подсказки на русском языке и пишите код прямо в браузере — без необходимости что-либо устанавливать.

Начать курс

Почему тестирование TypeScript — это не страшно, а выгодно

Вы написали классную функцию на TypeScript, запустили проект — всё работает. Через неделю добавили новую фичу, а старая логика сломалась. Знакомо? Если да, то вам срочно нужно подружиться с тестированием. И не надо бояться: тесты — это не скучная обязаловка, а ваш личный «детектор багов», который работает 24/7.

В этой статье мы разберём, с чего начать тестирование TypeScript новичку. Вы узнаете, как настроить окружение, написать первый unit-тест и не запутаться в типах. Никакой воды — только практика и реальные примеры кода.

Зачем вообще тестировать TypeScript, если он уже безопасный?

TypeScript действительно ловит много ошибок на этапе компиляции: неправильные типы, отсутствующие поля, неверные аргументы. Но статическая типизация не спасает от логических ошибок. Ваша функция может идеально проходить компиляцию, но выдавать неверный результат. Например:

function sum(a: number, b: number): number {
  return a - b; // Ошибка! Вместо сложения — вычитание
}

TypeScript не ругнётся — типы соблюдены. А вот юнит-тест сразу покажет, что sum(2, 2) не равно 4. Поэтому тестирование TypeScript — это не прихоть, а необходимость для любого серьёзного проекта.

Шаг 1. Выбираем инструмент: почему Jest — лучший друг новичка

На рынке есть несколько популярных фреймворков для тестирования: Mocha, Jasmine, Vitest, Jest. Для начинающих я настоятельно рекомендую Jest. Почему?

  • Работает «из коробки» — не нужно долго настраивать.
  • Встроенный mock-механизм и покрытие кода.
  • Отличная поддержка TypeScript через ts-jest.
  • Понятные сообщения об ошибках.

Давайте установим Jest в ваш проект. Предполагаю, что TypeScript у вас уже есть. Если нет — создайте новый проект:

mkdir my-ts-project
cd my-ts-project
npm init -y
npm install typescript jest @types/jest ts-jest --save-dev

Теперь создадим файл jest.config.js в корне проекта:

module.exports = {
  preset: 'ts-jest',
  testEnvironment: 'node',
  roots: ['/src'],
  testMatch: ['**/__tests__/**/*.ts', '**/?(*.)+(spec|test).ts'],
};

И добавим скрипт в package.json:

"scripts": {
  "test": "jest",
  "test:watch": "jest --watch"
}

Готово! Теперь можно писать тесты.

Шаг 2. Пишем первый тест на TypeScript

Создадим простую функцию в файле src/math.ts:

export function add(a: number, b: number): number {
  return a + b;
}

export function divide(a: number, b: number): number {
  if (b === 0) {
    throw new Error('Деление на ноль запрещено');
  }
  return a / b;
}

Теперь напишем для неё тест. Создайте папку src/__tests__/ и файл math.test.ts:

import { add, divide } from '../math';

describe('Math functions', () => {
  test('adds two numbers correctly', () => {
    expect(add(2, 3)).toBe(5);
    expect(add(-1, 1)).toBe(0);
    expect(add(0, 0)).toBe(0);
  });

  test('divides two numbers', () => {
    expect(divide(10, 2)).toBe(5);
    expect(divide(9, 3)).toBe(3);
  });

  test('throws error when dividing by zero', () => {
    expect(() => divide(5, 0)).toThrow('Деление на ноль запрещено');
  });
});

Запускаем npm test и видим зелёный отчёт. Поздравляю — вы только что написали свои первые unit-тесты на TypeScript!

Что здесь произошло?

  • describe — объединяет тесты в логическую группу.
  • test или it — отдельный тест-кейс.
  • expect — утверждение, которое проверяет результат.
  • toBe, toThrow — «матчеры» (сравниватели).

Шаг 3. Тестируем асинхронный код и промисы

Современный TypeScript-код часто работает с async/await. Jest это отлично поддерживает. Допустим, у нас есть функция, которая имитирует запрос к API:

// src/api.ts
export async function fetchUser(id: number): Promise<{ name: string; age: number }> {
  return new Promise((resolve) => {
    setTimeout(() => {
      resolve({ name: 'Alice', age: 30 });
    }, 100);
  });
}

Тест для неё:

// src/__tests__/api.test.ts
import { fetchUser } from '../api';

describe('API calls', () => {
  test('returns user by id', async () => {
    const user = await fetchUser(1);
    expect(user).toEqual({ name: 'Alice', age: 30 });
    expect(user.name).toBe('Alice');
  });

  test('user age is a number', async () => {
    const user = await fetchUser(2);
    expect(typeof user.age).toBe('number');
  });
});

Обратите внимание: мы используем toEqual для глубокого сравнения объектов, а не toBe. Это важно — toBe сравнивает ссылки, а toEqual — содержимое.

Шаг 4. Мокаем зависимости (чтобы тесты были быстрыми)

Когда вы тестируете модуль, который обращается к базе данных или внешнему API, не нужно делать реальные запросы. Вместо этого мы «мокаем» (подменяем) зависимость. Jest предоставляет для этого мощный инструмент — jest.mock.

Создадим сервис, который использует наш «API»:

// src/userService.ts
import { fetchUser } from './api';

export async function getUserSummary(id: number): Promise {
  const user = await fetchUser(id);
  return `${user.name} is ${user.age} years old`;
}

Теперь замокаем fetchUser в тесте:

// src/__tests__/userService.test.ts
import { getUserSummary } from '../userService';
import { fetchUser } from '../api';

jest.mock('../api'); // Jest автоматически замокает весь модуль

const mockedFetchUser = fetchUser as jest.Mock;

describe('UserService', () => {
  beforeEach(() => {
    mockedFetchUser.mockClear();
  });

  test('returns formatted summary', async () => {
    mockedFetchUser.mockResolvedValue({ name: 'Bob', age: 25 });

    const summary = await getUserSummary(1);
    expect(summary).toBe('Bob is 25 years old');
    expect(mockedFetchUser).toHaveBeenCalledTimes(1);
    expect                

Блоги

Рекомендаций по книгам