webroad.online
  1. 1Веб
  2. 2HTML
  3. 3CSS
  4. 4JavaScript
  5. 5TypeScript
  6. 6Git
  7. 7Инструменты
  8. 8React
  9. 9Стейт-менеджмент
  10. 10Next.js
  11. 11Формы
  12. 12Данные и бэкенд
  13. 13SEO
  14. 14Tailwind CSS
  15. 15Анимации
  16. 16Тестирование
  17. 17Архитектура
Тестирование · Урок 2 из 4

Vitest: unit-тесты

describe/test/expect, правильные матчеры, моки и поддельные таймеры.

Обновлено

Что такое Vitest

Vitest — тестраннер: находит файлы тестов (*.test.ts), запускает их и сообщает, что прошло, а что нет. Он быстрый, понимает TypeScript и ESM без настройки, а его API совместим с Jest (самым известным раннером).

npm i -D vitest
npx vitest          # режим watch — перезапуск при каждом сохранении
npx vitest run      # однократный запуск (CI)

Структура

// src/shared/lib/price.test.ts
import { describe, expect, test } from 'vitest'
import { applyDiscount } from './price'

describe('applyDiscount', () => {
  test('WELCOME10 снижает на 10%', () => {
    expect(applyDiscount(100, 'WELCOME10')).toBe(90)
  })

  test('неизвестный код не меняет цену', () => {
    expect(applyDiscount(100, 'NOPE')).toBe(100)
  })
})
  • describe группирует связанные тесты.
  • test (или it) — один случай.
  • expect(значение).матчер(ожидаемое) — проверка.

Кладите тест рядом с проверяемым файлом (colocation) — легко найти, переезжает вместе с ним.

Матчеры — виды и когда

Матчер Сравнивает Когда
toBe(x) идентичность (Object.is) примитивы: числа, строки, boolean
toEqual(x) содержимое, рекурсивно объекты и массивы
toStrictEqual(x) содержимое + undefined + класс когда важна точность
toBeTruthy() / toBeNull() / toBeUndefined() особые значения —
toContain(x) элемент в массиве / подстрока списки, тексты
toHaveLength(n) длина списки
toThrow(msg?) функция бросает ошибку валидация
resolves / rejects Promise асинхронный код
expect({ a: 1 }).toBe({ a: 1 })      // ✗ разные объекты
expect({ a: 1 }).toEqual({ a: 1 })   // ✓ одинаковое содержимое
expect(() => parseAge(-1)).toThrow('Invalid age')
await expect(loadUser(1)).resolves.toEqual({ id: 1 })

Моки

Мок — фальшивая функция, которая заменяет зависимость (API, время, случайность), чтобы тест был быстрым и детерминированным.

import { vi } from 'vitest'

const onSave = vi.fn()                       // функция-шпион
render(<Form onSave={onSave} />)
// ... пользователь отправляет форму
expect(onSave).toHaveBeenCalledWith({ email: 'a@x.com' })

vi.useFakeTimers()                           // вы управляете временем
vi.advanceTimersByTime(300)                  // например, для debounce
Вид Что делает
vi.fn() функция, записывающая вызовы
vi.spyOn(obj, 'method') шпионит за существующим методом
vi.mock('./api') подменяет целый модуль
vi.useFakeTimers() управляемое время

Не злоупотребляйте моками: чем больше вы подменяете, тем меньше реальности проверяете. Для HTTP-запросов MSW перехватывает их на уровне сети — код остаётся нетронутым.

Настройка с Next.js

У Next есть официальный гайд по Vitest (с @vitejs/plugin-react и jsdom для компонентов). Внимание: асинхронные Server Components пока плохо тестируются unit-тестами — для них используйте E2E.

Коротко

  • Vitest запускает *.test.ts; describe / test / expect.
  • toBe для примитивов, toEqual для объектов.
  • vi.fn и поддельные таймеры для зависимостей; подменяйте как можно меньше.

Официальные источники

Упражнения

Была ли страница полезной?

Один клик — без регистрации.