Test Runner

Vitest

Vitest est le runner de tests rapide et natif à Vite. Il réutilise votre configuration de build, exécute les tests en parallèle et propose des API compatibles avec Jest avec un support TypeScript de premier ordre.

intermediate13 min readUpdated 15 sept. 2026
sum.test.ts
ts
// sum.test.ts
import { describe, it, expect } from "vitest";
import { sum } from "./sum";

describe("sum", () => {
  it("adds two numbers", () => {
    expect(sum(2, 3)).toBe(5);
  });

  it("handles negatives", () => {
    expect(sum(-1, -1)).toBe(-2);
  });
});
Propulsé par
Vite
API
Compatible Jest
Langage
TypeScript natif
Mocks
vi.fn, vi.mock
Mode Watch
Instantané, Vite HMR
Mode Navigateur
Tests en navigateur réel

Pourquoi c'est important

Pourquoi Vitest s'impose

Rapide par défaut

Les tests passent par le pipeline de transformation de Vite via des workers parallèles, rendant le feedback quasi instantané, même pour les suites de tests volumineuses.

Réutilise votre config

Les alias, plugins et paramètres TypeScript proviennent de la même configuration Vite que votre application, évitant ainsi toute duplication.

API compatible Jest

describe, it, expect et les helpers de mocking reflètent Jest, ce qui rend la migration et le partage de connaissances très simples.

Le tableau complet

Les trois piliers de Vitest

Un pipeline natif Vite, une API compatible Jest et des workers parallèles pour maintenir une boucle de feedback rapide.

Le runner

Exécuter

Recherche les fichiers de tests, les exécute dans des workers parallèles et rapporte les résultats avec une UI claire et rapide.

La transformation

Build

Utilise Vite pour compiler TypeScript, JSX et les alias exactement comme le fait votre application.

Assertions et mocks

Vérifier

expect, vi.fn et vi.mock couvrent les assertions, les spies et le mocking de modules.

Vitest en un coup d'œil

Le cœur de Vitest

describe et it

Groupez les tests liés et nommez chacun d'eux selon le comportement qu'il vérifie.

expect

Une API de matchers riche pour les valeurs, les objets, les erreurs et les résultats asynchrones.

vi.fn et vi.spyOn

Créez des mocks et des spies pour isoler le code testé.

vi.mock

Remplacez un module entier par un mock, hoisté au-dessus des imports.

Tests asynchrones

Attendez les promesses et utilisez expect.resolves ou expect.rejects.

Couverture et UI

Rapports de couverture intégrés et UI optionnelle dans le navigateur.

Un bref aperçu

Un runner de tests conçu pour Vite

  1. 2021

    Annonce de Vitest

    Anthony Fu présente un runner de tests natif Vite qui réutilise le pipeline existant.

    21
  2. 2022

    Bases de Vitest 1.0

    Des releases rapides ajoutent la couverture de code, le mode navigateur et la compatibilité Jest.

    22
  3. 2024

    Vitest 1 et 2

    Stabilisation de l'API, introduction des projets workspace et maturité du mode navigateur.

    24
  4. Aujourd'hui

    Le standard pour Vite

    Le runner de tests recommandé pour Vite, Vue, Svelte, Solid et de nombreuses configurations React.

    Aujourd'hui

Le guide complet

Vitest: Tout ce que vous devez savoir

Qu’est-ce que Vitest ?

Vitest est un test runner propulsé par Vite. Il réutilise votre configuration Vite existante — alias, plugins, transformations TypeScript et JSX — afin que vos tests passent par le même pipeline que votre application. Cette base commune est ce qui lui permet de démarrer rapidement et de rester performant.

L’API vous semblera familière si vous avez déjà utilisé Jest. describe, it, expect et les outils de mocking fonctionnent de la même manière. Ce qui change, c’est le moteur sous-jacent : Vitest exécute les tests dans des workers en parallèle, surveille les fichiers via le graphe de modules de Vite et offre un support TypeScript natif sans configuration supplémentaire.

Écrire votre premier test

Un fichier de test importe des éléments depuis vitest et décrit le comportement qu’il vérifie.

// sum.test.ts
import { describe, it, expect } from "vitest";
import { sum } from "./sum";

describe("sum", () => {
  it("adds two numbers", () => {
    expect(sum(2, 3)).toBe(5);
  });

  it("handles negatives", () => {
    expect(sum(-1, -1)).toBe(-2);
  });
});

Nommez vos tests en fonction du comportement et non de la fonction. Un test en échec intitulé « ajoute deux nombres » vous indique précisément ce qui est cassé ; un test intitulé « test somme 1 » ne vous apporte aucune information. Groupez les cas liés avec describe et utilisez beforeEach et afterEach pour la configuration et le nettoyage.

Assertions

Vitest propose une API de matchers complète, très proche de celle de Jest.

// assertions.test.ts
expect(value).toBe(5);              // strict equality
expect(value).toEqual({ a: 1 });    // deep equality
expect(value).toBeTruthy();
expect(list).toHaveLength(3);
expect(list).toContain("a");
expect(fn).toThrow("invalid");
expect(value).toBeGreaterThan(3);

Utilisez toEqual pour les objets et les tableaux, et toBe pour les primitives et les vérifications de référence. toMatchObject et toContainEqual sont utiles lorsque vous ne vous intéressez qu’à une partie d’une structure.

Mocks et spies

L’isolation est au cœur des tests unitaires. Vitest propose vi.fn pour les mocks, vi.spyOn pour encapsuler des méthodes existantes et vi.mock pour remplacer des modules entiers.

// api.test.ts
import { vi, describe, it, expect } from "vitest";
import { fetchUser } from "./api";

vi.mock("./http", () => ({
  get: vi.fn().mockResolvedValue({ id: 1, name: "Ada" }),
}));

describe("fetchUser", () => {
  it("returns the user", async () => {
    await expect(fetchUser(1)).resolves.toEqual({ id: 1, name: "Ada" });
  });
});

vi.mock est “hoisted” (remonté) au-dessus des imports, ainsi le mock est enregistré avant que le module testé ne le charge. Lorsque la factory a besoin d’une variable définie dans le fichier de test, utilisez vi.hoisted pour que la valeur existe avant l’exécution du mock.

Tests asynchrones

Attendez la fin de l’opération et effectuez des assertions sur le résultat. Vitest fournit les helpers resolves et rejects pour les promesses.

// async.test.ts
it("rejects on failure", async () => {
  await expect(loadUser(-1)).rejects.toThrow("Invalid id");
});

Privilégiez ce style au callback done. Oublier done provoque des timeouts difficiles à diagnostiquer, et les rejets non gérés peuvent s’infiltrer d’un test à l’autre. Pour les timers factices, vi.useFakeTimers() et vi.advanceTimersByTime() vous permettent de tester les debounces et les intervalles de manière déterministe.

Snapshots

Les snapshots capturent une valeur pour la comparer lors des exécutions ultérieures. Ils sont utiles pour les sorties volumineuses et stables, comme des données sérialisées ou du markup rendu, mais ils sont faciles à utiliser à mauvais escient.

// snapshot.test.ts
it("matches the shape", () => {
  expect(createConfig({ debug: true })).toMatchSnapshot();
});

Un snapshot mis à jour sans être relu est pire qu’une absence de test. Utilisez-les pour des structures de données où une comparaison complète est impraticable, et privilégiez les assertions explicites lorsque vous savez précisément ce qui importe. toMatchInlineSnapshot conserve la valeur attendue dans le fichier de test, ce qui rend les revues de code pertinentes.

Configuration

Vitest lit un bloc test depuis votre configuration Vite ou un vitest.config.ts dédié.

// vitest.config.ts
import { defineConfig } from "vitest/config";

export default defineConfig({
  test: {
    environment: "jsdom",
    globals: true,
    coverage: {
      provider: "v8",
      reporter: ["text", "html"],
      thresholds: { lines: 80 },
    },
  },
});

L’option environment permet de choisir entre node, jsdom, happy-dom ou un navigateur. Pour les tests de composants, jsdom ou happy-dom sont généralement utilisés ; pour la logique pure, conservez l’environnement node qui est plus rapide. Les seuils de couverture (coverage thresholds) permettent de transformer un objectif de couverture en une règle contraignante.

Vitest et la pyramide des tests

Vitest constitue la couche des tests unitaires et d’intégration. Associez-le à une bibliothèque de tests de composants telle que Testing Library pour le comportement de l’UI, et à un outil de bout en bout comme Playwright pour les flux utilisateurs complets. Ensemble, ils couvrent la pyramide : de nombreux tests unitaires rapides, moins de tests d’intégration et une poignée de tests de bout en bout.

Bonnes pratiques

  • Testez le comportement, pas les détails d’implémentation.
  • Chaque test doit se concentrer sur un seul comportement.
  • Utilisez beforeEach pour la configuration partagée et nettoyez vos mocks avec vi.clearAllMocks.
  • Privilégiez resolves et rejects aux callbacks done.
  • Mockez aux frontières (réseau, temps, aléatoire), et non chaque appel interne.
  • Utilisez des seuils de couverture (coverage thresholds) pour éviter les régressions silencieuses.
  • Exécutez vos tests en mode watch pendant le développement et en CI à chaque push.

Erreurs courantes

  • Effectuer des assertions sur l’état interne ou des méthodes privées plutôt que sur le comportement observable.
  • Mettre à jour les snapshots sans examiner le diff.
  • Oublier de réinitialiser les mocks entre les tests, entraînant ainsi des fuites d’état.
  • Utiliser des timers réels, ce qui rend les tests lents et instables (flaky).
  • Trop mocker au point que le test ne vérifie plus que les mocks eux-mêmes.
  • Tester le même comportement à chaque niveau de la pyramide.

Et après ?

Vitest est le moyen le plus rapide de commencer à tester un projet Vite. Comparez-le avec le classique Jest, ajoutez Testing Library pour vos composants et Playwright pour vos flux de bout en bout, et appuyez-vous sur Vite pour maintenir une configuration partagée. Ensuite, écrivez quelques tests pour votre code existant et voyez vos refactorisations devenir sécurisées.

Tester du code asynchrone

Attendez la promesse et faites l'assertion sur le résultat. Le callback done est facile à oublier et produit des timeouts confus.

Préférer
it("loads the user", async () => {
  await expect(getUser(1)).resolves.toEqual({
    id: 1,
    name: "Ada",
  });
});
Éviter
it("loads the user", (done) => {
  getUser(1).then((user) => {
    expect(user.name).toBe("Ada");
    done();
  });
});

Mocker un module

vi.mock est hoisté au-dessus des imports, ainsi le module est remplacé avant que le code testé ne le charge.

Préférer
import { vi } from "vitest";

vi.mock("./api", () => ({
  fetchUser: vi.fn().mockResolvedValue({
    id: 1,
  }),
}));
Éviter
import * as api from "./api";
// reassigning after import
// is brittle and often fails
api.fetchUser = async () => ({ id: 1 });

FAQ

Foire aux questions

Keep learning

Related topics from the roadmap.

$ commencer à apprendre

Prêt à apprendre Vitest ?

Notre tutoriel interactif vous guide à travers Vitest pas à pas — avec des quiz et du vrai code que vous pouvez exécuter dans le navigateur.