Перейти к содержимому

vitest-auto-spyТипизированный спай для каждого метода класса

Передайте класс и получите объект, где каждый метод - спай с типами из класса и хелперами под свой тип возврата. Один API на Vitest, Bun, node:test и Rstest.

user.service.spec.ts
const users = createSpyFromClass(UserService);

users.load.resolveWith(user);
users.save.rejectWith(new HttpError(409));

users.load.mustBeCalledWith(7);
✓ 3 passed no casts · no vi.fn() kept in sync by hand

01 / Суть

Хватит синхронизировать мок руками ​

Мок, который пишут сегодня ​

ts
const users = {
  load: vi.fn(),
  save: vi.fn(),
  remove: vi.fn(),
} as unknown as UserService;

vi.mocked(users.load).mockResolvedValue(user);
vi.mocked(users.save).mockRejectedValue(new HttpError(409));

Строка, которая его заменяет ​

ts
import { type Spy, createSpyFromClass } from 'vitest-auto-spy';

const users: Spy<UserService> = createSpyFromClass(UserService);

users.load.resolveWith(user);
users.save.rejectWith(new HttpError(409));

Каст больше не нужен. Из-за каста после переименования метода в UserService рукописный объект всё ещё компилируется и тест всё ещё зелёный, но уже ничего не проверяет. Spy<UserService> типизирован по классу, поэтому то же переименование делает спеку красной. Настоящий конструктор не выполняется, так что зависимости самого сервиса мокать не нужно. Класса нет? createAutoMock<T>() строит те же спаи по типу или интерфейсу.

Начало работы · createSpyFromClass · Управляющие хелперы

02 / Установка

Установка и импорт ​

bash
npm i -D vitest-auto-spy

Импортируйте из точки входа под свой раннер тестов. Всё, что после этой строки, одинаково.

ts
import { createSpyFromClass } from 'vitest-auto-spy'; // Vitest, без настройки
import { createSpyFromClass } from 'vitest-auto-spy/bun'; // bun:test
import { createSpyFromClass } from 'vitest-auto-spy/node'; // node:test
import { createSpyFromClass } from 'vitest-auto-spy/rstest'; // Rstest

Своих рантайм-зависимостей у пакета нет. rxjs и пакеты @angular/* нужны только своим точкам входа. Спеки с TestBed в Angular импортируют provideAutoSpy и injectSpy из vitest-auto-spy/angular (Angular 20 или новее); createSpyFromClass работает в любой спеке. Подробнее — Установка.

03 / Медленные тесты

Какой тест медленный и почему ​

Vitest печатает один Duration на весь прогон. perf показывает файлы тестов, которые правда медленные, перемеряет каждый отдельно и показывает, куда ушло время процессора. Запускайте локально или в CI:

bash
npx vitest-auto-spy perf --gate
error  perf-gate-slow-file libs/player/src/lib/vod/vod.component.spec.ts
       The test bodies in this file add up to 9.20s, over the 5.00s budget (…). Re-measured on its own: 8.70s, still over budget.

       ┌─ measurements ────────────────────────────────────────────────
       │ tests             38   242ms each   20× the median test
       ├─ slowest tests ───────────────────────────────────────────────
       │  527ms  focus > moves through the controls
       ├─ where the time went · CPU profile, 8.41s sampled ────────────
       │ hooks        ███████████░░░░░░░░░ 54%   test bodies 46%
       │ by package   ██████░░░░░░░░░░░░░░  28%  jsdom
       │ in the spec  setUpWith 38%  ·  VodComponent_Template 17%  ·  assertFocus 8%
       ├─ likely cause ────────────────────────────────────────────────
       │ Most of the time is set-up that every test repeats: 54% is in hooks — setUpWith alone is 38%.
       └───────────────────────────────────────────────────────────────

Бюджет подстраивается под медианный тест того же прогона, поэтому быстрый ноутбук и медленная машина CI выносят одинаковый вердикт. Файл, который тормозил только из-за соседей, а один идёт быстро, помечается как не воспроизвелось, а не как ошибка. Профилировщик загружается только для перемера, так что обычный прогон ничего не платит. Для Angular-спек карточка ещё делит время на настройку TestBed, создание компонентов, обнаружение изменений и компиляцию. --code-quality пишет находки для виджета merge request в GitLab.

Порог · perf целиком · В CI

04 / Куда дальше

Начните оттуда, где вы уже стоите ​

0runtime-зависимостей
4среды, одно ядро
5адаптеров фреймворков
58правил линтера
100%покрытие ядра

05 / Уже что-то стоит

Если библиотека спаев в репозитории уже есть ​

У jest-auto-spies и jasmine-auto-spies тот же API. Кодмод переписывает импорты и вызовы и показывает diff до того, как что-то сохранить. Для Spectator, @testing-library/angular и Suites есть по странице, где их хелперы построчно сопоставлены с этими.

Что другие делают иначе · Перевести тесты · Что нового в 4.0

Опубликовано под лицензией MIT.