Vitest: основы, моки, spy
↑ 2.2 Тестирование: основы · ← Предыдущая · → Следующая
Зачем это на собесе
Vitest — стандарт для Vite-проектов; спрашивают моки модулей, spy и разницу с Jest.
Объяснение
Vitest — тест-раннер на Vite: те же трансформации, что и в приложении (TS, Vue SFC), быстрый watch/HMR, API совместим с Jest.
// vitest.config.ts
export default defineConfig({ test: { environment: "jsdom", globals: true, setupFiles: ["./test/setup.ts"], coverage: { provider: "v8" } } });import { vi, describe, it, expect, beforeEach } from "vitest";
// Mock функции
const cb = vi.fn().mockReturnValue(1);
cb(2); expect(cb).toHaveBeenCalledWith(2); expect(cb).toHaveBeenCalledTimes(1);
// Spy: следим за реальным методом
const spy = vi.spyOn(console, "error").mockImplementation(() => {});
// Мок модуля (hoisted)
vi.mock("./api", () => ({ fetchUser: vi.fn().mockResolvedValue({ id: 1, name: "A" }) }));
import { fetchUser } from "./api";
// Частичный мок
vi.mock("./utils", async (orig) => ({ ...(await orig<typeof import("./utils")>()), nowMs: () => 0 }));
beforeEach(() => { vi.clearAllMocks(); }); // clear: история; reset: + реализации; restore: + spyOn
afterEach(() => { vi.restoreAllMocks(); vi.unstubAllGlobals(); });
vi.stubGlobal("fetch", vi.fn().mockResolvedValue({ ok: true, json: async () => ({}) }));| Инструмент | Для чего |
|---|---|
vi.fn() | заглушка функции, запись вызовов |
vi.spyOn(obj, "m") | слежение/подмена метода |
vi.mock(path, factory) | замена модуля |
vi.stubGlobal/stubEnv | глобалы и переменные окружения |
vi.useFakeTimers() | таймеры и даты (см. Тестирование асинхронного кода и фейковые таймеры) |
expectTypeOf | тесты типов |
Coverage (v8/istanbul), --ui, in-source testing, workspaces | сопутствующие возможности |
Разница с Jest: нативные ESM и TS, vi вместо jest, hoisting vi.mock выполняется аналогично, скорость выше, единый конфиг с Vite.
Нюансы и подводные камни
vi.mockподнимается вверх файла: нельзя ссылаться на переменные, объявленные в тесте (используйтеvi.hoisted).- Не сбрасывать моки между тестами — источник зависимостей между тестами.
- Мок слишком глубоко — тест бесполезен; мокайте границы (сеть, время), а не свои модули.
environment: "jsdom"не полностью эмулирует браузер (нет layout).globals: trueтребует типов (vitest/globals).
Практика
- Настройте Vitest с jsdom, coverage и setup-файлом.
- Замокайте API-модуль и проверьте, что компонент/функция вызывает его с нужными аргументами.
- Проверьте вызов
console.errorчерез spy.
Вопросы с ответами
Чем
vi.fnотличается отvi.spyOn?
fnсоздаёт новую заглушку,spyOnоборачивает существующий метод, сохраняя возможность вызова оригинала.
Чем Vitest отличается от Jest?
Работает на Vite (быстро, нативные ESM/TS), совместимый API, единая конфигурация с приложением.