Skip to content
Vitest 3
Main Navigation Руководство & APIКонфигурацияРежим браузераРасширенный API
3.2.0
2.1.9
1.6.1
0.34.6

Русский

English
简体中文
繁體中文
Español
Français
Português – Brasil
Deutsch
日本語
한국어
Italiano
Polski
Türkçe
čeština
magyar

Русский

English
简体中文
繁體中文
Español
Français
Português – Brasil
Deutsch
日本語
한국어
Italiano
Polski
Türkçe
čeština
magyar

Внешний вид

Sidebar Navigation

Введение

Почему Vitest

Начало работы

Возможности

Настройка Vitest

API

Справочник по API тестирования

Мок-функции

Vi

expect

expectTypeOf

assert

assertType

Руководство

Интерфейс командной строки

Фильтрация тестов

Тестовые проекты

Средства отчётности

Покрытие кода

Снапшот-тестирование

Мокирование

Параллелизм

Тестирование типов

Vitest UI

Тестирование в исходном коде

Контекст теста

Аннотации тестов

Среда тестирования

Расширение матчеров

Интеграции с IDE

Отладка

Распространенные ошибки

Руководство по миграции

Миграция на Vitest 3.0

Миграция с Jest

Производительность

Профилирование производительности тестов

Улучшение производительности

Режим браузера

Расширенный API

Сравнение с другими тестовыми раннерами

Содержание страницы

Руководство по миграции ​

Миграция на Vitest 3.0 ​

Параметры теста как третий аргумент ​

Vitest 3.0 выводит предупреждение, если вы передаете объект в качестве третьего аргумента функциям test или describe:

ts
test('validation works', () => {
  // ...
}, { retry: 3 }); 

test('validation works', { retry: 3 }, () => { 
  // ...
});

В следующей основной версии будет генерироваться ошибка, если третий аргумент является объектом. Обратите внимание, что таймаут в числовом формате остается поддерживаемым:

ts
test('validation works', () => {
  // ...
}, 1000); // Ok ✅

browser.name и browser.providerOptions устарели ​

Обе опции browser.name и browser.providerOptions будут удалены в Vitest 4. Вместо них следует использовать новую опцию browser.instances:

ts
export default defineConfig({
  test: {
    browser: {
      name: 'chromium', 
      providerOptions: { 
        launch: { devtools: true }, 
      }, 
      instances: [ 
        { 
          browser: 'chromium', 
          launch: { devtools: true }, 
        }, 
      ], 
    },
  },
})

С новым полем browser.instances вы также можете указать несколько конфигураций браузера.

spy.mockReset теперь восстанавливает исходную реализацию ​

Раньше не существовало удобного способа сбросить мок до его исходной реализации без повторного применения шпиона. Теперь spy.mockReset сбрасывает функцию реализации на исходную, а не на фиктивную noop.

ts
const foo = {
  bar: () => 'Hello, world!',
};

vi.spyOn(foo, 'bar').mockImplementation(() => 'Hello, mock!');

foo.bar(); // 'Hello, mock!'

foo.bar.mockReset();

foo.bar(); // undefined
foo.bar(); // 'Hello, world!'

vi.spyOn повторно использует мок, если метод уже замокан ​

Ранее Vitest всегда назначал новый шпион при создании шпиона для объекта. Это приводило к ошибкам с mockRestore, потому что он восстанавливал шпиона до предыдущего шпиона вместо исходной функции:

ts
vi.spyOn(fooService, 'foo').mockImplementation(() => 'bar');
vi.spyOn(fooService, 'foo').mockImplementation(() => 'bar');
vi.restoreAllMocks();
vi.isMockFunction(fooService.foo); // true
vi.isMockFunction(fooService.foo); // false

Поведение фиктивных таймеров по умолчанию ​

Vitest больше не предоставляет опции fakeTimers.toFake по умолчанию. Теперь Vitest будет имитировать любой API, связанный с таймерами, если он доступен (кроме nextTick). В частности, performance.now() теперь имитируется при вызове vi.useFakeTimers.

ts
vi.useFakeTimers();

performance.now(); // original
performance.now(); // fake

Вы можете вернуться к предыдущему поведению, указав таймеры при вызове vi.useFakeTimers или глобально в конфигурации:

ts
export default defineConfig({
  test: {
    fakeTimers: {
      toFake: [ 
        'setTimeout', 
        'clearTimeout', 
        'setInterval', 
        'clearInterval', 
        'setImmediate', 
        'clearImmediate', 
        'Date', 
      ] 
    },
  },
})

Ужесточение сравнения ошибок ​

Vitest теперь проверяет больше свойств при сравнении ошибок с помощью toEqual или toThrowError. Vitest теперь сравнивает name, message, cause и AggregateError.errors. Для Error.cause сравнение выполняется асимметрично:

ts
expect(new Error('hi', { cause: 'x' })).toEqual(new Error('hi')); // ✅
expect(new Error('hi')).toEqual(new Error('hi', { cause: 'x' })); // ❌

В дополнение к проверке большего количества свойств, Vitest теперь сравнивает прототипы ошибок. Например, если был выброшен TypeError, сравнение должно ссылаться на TypeError, а не на Error:

ts
expect(() => {
  throw new TypeError('type error');
})
  .toThrowError(new Error('type error')) 
  .toThrowError(new TypeError('type error')); 

Подробнее см. в PR: #5876.

Условный экспорт module не разрешается по умолчанию в Vite 6 ​

Vite 6 позволяет использовать более гибкие опции resolve.conditions, и Vitest настраивает его так, чтобы по умолчанию исключать условный экспорт module. См. также руководство по миграции Vite 6 для получения подробной информации об изменениях на стороне Vite.

Тип Custom объявлен устаревшим API ​

Тип Custom теперь является синонимом типа Test. Обратите внимание, что Vitest обновил публичные типы в 2.1 и изменил экспортируемые имена на RunnerCustomCase и RunnerTestCase:

ts
import {
  RunnerCustomCase, 
  RunnerTestCase, 
} from 'vitest';

Если вы используете getCurrentSuite().custom(), type возвращаемой задачи теперь равен 'test'. Тип Custom будет удален в Vitest 4.

Тип WorkspaceSpec не используется API ​

В публичном API этот тип ранее использовался в пользовательских секвенсорах. Пожалуйста, перейдите на TestSpecification вместо него.

onTestFinished и onTestFailed теперь получают контекст ​

Хуки onTestFinished и onTestFailed ранее получали результат теста в качестве первого аргумента. Теперь они получают контекст теста, подобно beforeEach и afterEach.

Изменения в Snapshot API API ​

Публичный Snapshot API в @vitest/snapshot был изменен для поддержки нескольких состояний за один запуск. Подробнее см. в PR: #6817

Обратите внимание, что эти изменения затрагивают только разработчиков, использующих Snapshot API напрямую. Изменений в API .toMatchSnapshot не было.

Изменения в сигнатуре типа resolveConfig API ​

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

Эта функция не имеет внутреннего использования и предоставляется исключительно как публичный API.

Упорядочены типы vitest/reporters API ​

Точка входа vitest/reporters теперь экспортирует только реализации репортеров и типы параметров. Если вам нужен доступ к TestCase/TestSuite и другим типам, связанным с задачами, импортируйте их дополнительно из vitest/node.

Покрытие игнорирует тестовые файлы, даже если coverage.excludes переопределен. ​

Больше невозможно включать тестовые файлы в отчет о покрытии, переопределяя coverage.excludes. Тестовые файлы теперь всегда исключаются.

Миграция на Vitest 2.0 ​

Пул по умолчанию: forks ​

Vitest 2.0 изменяет конфигурацию по умолчанию для pool на 'forks' для повышения стабильности. Вы можете прочитать полную мотивацию в PR.

Если вы использовали poolOptions без явного указания pool, вам может потребоваться обновить конфигурацию:

ts
export default defineConfig({
  test: {
    poolOptions: {
      threads: { 
        singleThread: true, 
      }, 
      forks: { 
        singleFork: true, 
      }, 
    }
  }
})

Хуки выполняются последовательно ​

До Vitest 2.0 все хуки выполнялись параллельно. В 2.0 все хуки выполняются последовательно. Кроме того, хуки afterAll/afterEach выполняются в порядке, обратном их объявлению.

Чтобы вернуться к параллельному выполнению хуков, измените sequence.hooks на 'parallel':

ts
export default defineConfig({
  test: {
    sequence: { 
      hooks: 'parallel', 
    }, 
  },
})

suite.concurrent запускает все тесты параллельно ​

Ранее указание concurrent для набора тестов группировало параллельные тесты внутри наборов, запуская их последовательно. Теперь, следуя поведению Jest, все тесты запускаются параллельно (с учетом ограничений maxConcurrency).

coverage.ignoreEmptyLines в V8 Coverage включен по умолчанию ​

Значение по умолчанию для coverage.ignoreEmptyLines теперь true. Это значительное изменение может повлиять на отчеты о покрытии кода и потребовать корректировки порогов покрытия для некоторых проектов. Эта корректировка затрагивает только настройку по умолчанию, когда coverage.provider равен 'v8'.

Удаление опции watchExclude ​

Vitest использует механизм наблюдения Vite. Файлы или каталоги исключаются путем добавления их в server.watch.ignored:

ts
export default defineConfig({
  server: { 
    watch: { 
      ignored: ['!node_modules/examplejs'] 
    } 
  } 
})

--segfault-retry удален ​

В связи с изменениями в пуле по умолчанию эта опция больше не нужна. Если вы столкнулись с ошибками сегментации памяти, попробуйте переключиться на пул 'forks'. Если проблема не исчезнет, пожалуйста, откройте новую проблему с воспроизведением.

Удалена пустая задача из наборов задач ​

Это изменение в расширенном API задач. Ранее перебор .suite в конечном итоге приводил к пустой внутренней задаче, используемой вместо файловой.

Это делает .suite необязательным; если задача определена на верхнем уровне, у нее не будет связанного набора. Вы можете вернуться к свойству .file, которое теперь присутствует во всех задачах (включая саму файловую задачу, поэтому будьте внимательны, чтобы избежать бесконечной рекурсии).

Это изменение также удаляет файл из expect.getState().currentTestName и делает expect.getState().testPath обязательным для указания.

task.meta добавлен в JSON Reporter ​

JSON-репортер теперь отображает task.meta для каждого результата проверки.

Упрощение общих типов мок-функций (например, vi.fn<T>, Mock<T>) ​

Ранее vi.fn<TArgs, TReturn> принимал два отдельных общих типа для аргументов и возвращаемого значения соответственно. Это изменено на прямое использование типа функции vi.fn<T> для упрощения использования.

ts
import { vi } from 'vitest';
import type { Mock } from 'vitest';

const add = (x: number, y: number): number => x + y;

// using vi.fn<T>
const mockAdd = vi.fn<Parameters<typeof add>, ReturnType<typeof add>>(); 
const mockAdd = vi.fn<typeof add>(); 

// using Mock<T>
const mockAdd: Mock<Parameters<typeof add>, ReturnType<typeof add>> = vi.fn(); 
const mockAdd: Mock<typeof add> = vi.fn(); 

Доступ к результатам mock.results после разрешения промисов ​

Ранее Vitest разрешал промисы mock.results, если функция возвращала Promise. Теперь есть отдельное свойство mock.settledResults, которое заполняется только после того, как возвращенный Promise разрешен или отклонен.

ts
const fn = vi.fn().mockResolvedValueOnce('result');
await fn();

const result = fn.mock.results[0]; // 'result'
const result = fn.mock.results[0]; // 'Promise<result>'

const settledResult = fn.mock.settledResults[0]; // 'result'

С этим изменением мы также вводим новые матчеры toHaveResolved*, аналогичные toHaveReturned, чтобы упростить миграцию для тех, кто ранее использовал toHaveReturned:

ts
const fn = vi.fn().mockResolvedValueOnce('result');
await fn();

expect(fn).toHaveReturned('result'); 
expect(fn).toHaveResolved('result'); 

Режим браузера ​

Режим браузера Vitest претерпел множество изменений в ходе бета-тестирования. Вы можете прочитать о нашей философии касательно режима браузера на странице обсуждения GitHub.

Большинство изменений были дополняющими (новыми функциями), но также присутствовали небольшие критические изменения:

  • Провайдер none был переименован в preview #5842
  • Провайдер preview теперь является значением по умолчанию #5842
  • indexScripts переименован в orchestratorScripts #5842

Удалены устаревшие опции ​

Некоторые устаревшие опции были удалены:

  • Команда vitest typecheck - вместо нее используйте vitest --typecheck
  • Переменные окружения VITEST_JUNIT_CLASSNAME и VITEST_JUNIT_SUITE_NAME (вместо них используйте опции репортера)
  • Проверка покрытия c8 (вместо нее используйте coverage-v8)
  • Экспорт SnapshotEnvironment из vitest - импортируйте его из vitest/snapshot вместо этого
  • SpyInstance удален в пользу MockInstance

Миграция на Vitest 1.0 ​

Минимальные требования ​

Vitest 1.0 требует Vite 5.0 и Node.js 18 или выше.

Все подпакеты @vitest/* требуют Vitest версии 1.0 или выше.

Обновление снимков #3961 ​

Кавычки в снимках больше не экранируются, и все снимки используют обратные кавычки (`) даже для однострочных строк.

  1. Кавычки больше не экранируются:
diff
expect({ foo: 'bar' }).toMatchInlineSnapshot(`
  Object {
-    \\"foo\\": \\"bar\\",
+    "foo": "bar",
  }
`)
  1. Однострочные снимки теперь используют кавычки "`" вместо ':
diff
- expect('some string').toMatchInlineSnapshot('"some string"')
+ expect('some string').toMatchInlineSnapshot(`"some string"`)

Также были изменения в пакете @vitest/snapshot. Если вы не используете его напрямую, вам ничего не нужно менять.

  • Вам больше не нужно расширять SnapshotClient только для переопределения метода equalityCheck: просто передайте его как isEqual при инициализации экземпляра
  • client.setTest был переименован в client.startCurrentRun
  • client.resetCurrent был переименован в client.finishCurrentRun

Пулы стандартизированы #4172 ​

Мы удалили множество опций конфигурации, чтобы упростить настройку раннера в соответствии с вашими требованиями. Пожалуйста, ознакомьтесь с примерами миграции, если вы полагаетесь на --threads или другие связанные флаги.

  • --threads теперь --pool=threads
  • --no-threads теперь --pool=forks
  • --single-thread теперь --poolOptions.threads.singleThread
  • --experimental-vm-threads теперь --pool=vmThreads
  • --experimental-vm-worker-memory-limit теперь --poolOptions.vmThreads.memoryLimit
  • --isolate теперь --poolOptions.<pool-name>.isolate и browser.isolate
  • test.maxThreads теперь test.poolOptions.<pool-name>.maxThreads
  • test.minThreads теперь test.poolOptions.<pool-name>.minThreads
  • test.useAtomics теперь test.poolOptions.<pool-name>.useAtomics
  • test.poolMatchGlobs.child_process теперь test.poolMatchGlobs.forks
  • test.poolMatchGlobs.experimentalVmThreads теперь test.poolMatchGlobs.vmThreads
diff
{
  scripts: {
-    "test": "vitest --no-threads"
     // For identical behaviour:
+    "test": "vitest --pool forks --poolOptions.forks.singleFork"
     // Or multi parallel forks:
+    "test": "vitest --pool forks"

  }
}
diff
{
  scripts: {
-    "test": "vitest --experimental-vm-threads"
+    "test": "vitest --pool vmThreads"
  }
}
diff
{
  scripts: {
-    "test": "vitest --isolate false"
+    "test": "vitest --poolOptions.threads.isolate false"
  }
}
diff
{
  scripts: {
-    "test": "vitest --no-threads --isolate false"
+    "test": "vitest --pool forks --poolOptions.forks.isolate false"
  }
}

Изменения в покрытии #4265, #4442 ​

Опция coverage.all теперь по умолчанию включена. Это означает, что все файлы проекта, соответствующие шаблону coverage.include, будут обработаны, даже если они не выполнялись.

Структура API порогов покрытия была изменена, и теперь она поддерживает указание порогов для конкретных файлов с использованием шаблонов glob:

diff
export default defineConfig({
  test: {
    coverage: {
-      perFile: true,
-      thresholdAutoUpdate: true,
-      100: true,
-      lines: 100,
-      functions: 100,
-      branches: 100,
-      statements: 100,
+      thresholds: {
+        perFile: true,
+        autoUpdate: true,
+        100: true,
+        lines: 100,
+        functions: 100,
+        branches: 100,
+        statements: 100,
+      }
    }
  }
})

Типы моков #4400 ​

Несколько типов были удалены в соответствии с именованием "Mock" в стиле Jest.

diff
- import { EnhancedSpy, SpyInstance } from 'vitest'
+ import { MockInstance } from 'vitest'

WARNING

SpyInstance устарел в пользу MockInstance и будет удален в следующем основном выпуске.

Моки таймеров #3925 ​

vi.useFakeTimers() больше не имитирует автоматически process.nextTick. По-прежнему можно имитировать process.nextTick, явно указав его с помощью vi.useFakeTimers({ toFake: ['nextTick'] }).

Однако имитация process.nextTick невозможна при использовании --pool=forks. Используйте другую опцию --pool, если вам нужна имитация process.nextTick.

Миграция с Jest ​

Vitest был разработан с Jest-совместимым API для максимально простой миграции с Jest. Несмотря на эти усилия, тем не менее, вы можете столкнуться со следующими различиями:

Глобальные переменные по умолчанию ​

Jest по умолчанию активирует свой глобальный API. Vitest не активирует его по умолчанию. Вы можете либо включить глобальные переменные через настройку конфигурации globals, либо вместо этого обновить свой код для использования импортов из модуля vitest.

Если вы решите оставить глобальные переменные отключенными, имейте в виду, что общие библиотеки, такие как testing-library, не будут автоматически очищать DOM.

spy.mockReset ​

Метод mockReset в Jest заменяет реализацию мока пустой функцией, возвращающей undefined.

mockReset в Vitest сбрасывает реализацию мока до его исходной. То есть, сброс мока, созданного vi.fn(impl), сбросит реализацию мока до impl.

Моки модулей ​

При мокировании модуля в Jest возвращаемое значение фабричного аргумента является экспортом по умолчанию. В Vitest аргумент фабрики должен возвращать объект, в котором каждый экспорт явно определен. Например, следующий jest.mock должен быть обновлен следующим образом:

ts
jest.mock('./some-path', () => 'hello') 
vi.mock('./some-path', () => ({ 
  default: 'hello', 
})) 

Для получения более подробной информации, пожалуйста, обратитесь к разделу API vi.mock.

Поведение автоматического мокирования ​

В отличие от Jest, мокированные модули в <root>/__mocks__ не загружаются, если не вызывается vi.mock(). Если вам нужно, чтобы они были мокированы в каждом тесте, как в Jest, вы можете мокировать их внутри setupFiles.

Импорт оригинала замоканного пакета ​

Если вы создаете частичный мок для пакета, вы могли ранее использовать функцию Jest requireActual. В Vitest вы должны заменить эти вызовы на vi.importActual.

ts
const { cloneDeep } = jest.requireActual('lodash/cloneDeep'); 
const { cloneDeep } = await vi.importActual('lodash/cloneDeep'); 

Применение моков к внешним библиотекам ​

В отличие от Jest, который делает это по умолчанию, при мокировании модуля и необходимости распространить это мокирование на другие внешние библиотеки, использующие тот же модуль, вы должны явно указать, какую стороннюю библиотеку вы хотите мокировать. Для этого внешняя библиотека должна быть включена в ваш исходный код с помощью server.deps.inline.

server.deps.inline: ["lib-name"]

expect.getState().currentTestName ​

Имена test в Vitest объединяются символом > для более четкого различения тестов и наборов, тогда как Jest использует пробел ().

diff
- `${describeTitle} ${testTitle}`
+ `${describeTitle} > ${testTitle}`

Переменные окружения ​

Как и Jest, Vitest устанавливает NODE_ENV в значение test, если он не был установлен ранее. Vitest также имеет аналог JEST_WORKER_ID под названием VITEST_POOL_ID (всегда меньше или равен maxThreads), поэтому, если вы на него полагаетесь, не забудьте его переименовать. Vitest также предоставляет VITEST_WORKER_ID, который является уникальным идентификатором запущенного воркера. Это число не зависит от maxThreads и будет увеличиваться с каждым созданным воркером.

Замена свойства ​

Если вы хотите изменить объект, в Jest вы бы использовали API replaceProperty. В Vitest для этого можно использовать vi.stubEnv или vi.spyOn.

Функция обратного вызова Done ​

Начиная с Vitest v0.10.0, стиль объявления тестов с колбэками устарел. Вы можете переписать их, используя функции async/await, или использовать Promise для имитации поведения колбэков.

js
it('should work', (done) => {  
it('should work', () => new Promise(done => { 
  // ...
  done()
}) 
})) 

Хуки ​

В Vitest хуки beforeAll/beforeEach могут возвращать функцию очистки. По этой причине вам может потребоваться переписать объявления ваших хуков, если они возвращают что-либо, кроме undefined или null:

ts
beforeEach(() => setActivePinia(createTestingPinia())) 
beforeEach(() => { setActivePinia(createTestingPinia()) }) 

В Jest хуки вызываются последовательно. По умолчанию Vitest запускает хуки параллельно. Чтобы использовать поведение Jest, обновите опцию sequence.hooks:

ts
export default defineConfig({
  test: {
    sequence: { 
      hooks: 'list', 
    } 
  }
})

Типы ​

Vitest не имеет аналога пространства имен jest, поэтому вам нужно будет импортировать типы напрямую из vitest:

ts
let fn: jest.Mock<(name: string) => number>; 
import type { Mock } from 'vitest'; 
let fn: Mock<(name: string) => number>; 

Таймеры ​

Vitest не поддерживает устаревшие таймеры Jest.

Таймаут ​

Если вы использовали jest.setTimeout, вам нужно будет перейти на vi.setConfig:

ts
jest.setTimeout(5_000); 
vi.setConfig({ testTimeout: 5_000 }); 

Снимки Vue ​

Это не специфичная для Jest функция, но если вы ранее использовали Jest с пресетом vue-cli, вам нужно будет установить пакет jest-serializer-vue и использовать его в setupFiles:

js
import { defineConfig } from 'vite';

export default defineConfig({
  test: {
    setupFiles: ['./tests/unit/setup.js'],
  },
});
js
import vueSnapshotSerializer from 'jest-serializer-vue';

expect.addSnapshotSerializer(vueSnapshotSerializer);

В противном случае ваши снимки будут содержать много экранированных кавычек.

Pager
Предыдущая страницаРаспространенные ошибки
Следующая страницаПрофилирование производительности тестов

Выпущено на условиях лицензии MIT.

Авторские права (c) 2021-Present Vitest Team

https://vitest.dev/guide/migration

Выпущено на условиях лицензии MIT.

Авторские права (c) 2021-Present Vitest Team