Skip to content
Vitest 3
Main Navigation Guide & APIConfigurationMode NavigateurAPI avancée
3.2.0
2.1.9
1.6.1
0.34.6

Français

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

Français

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

Apparence

Sidebar Navigation

Introduction

Pourquoi Vitest

Démarrage

Fonctionnalités

Configuration de Vitest

API

Référence de l'API des Tests

Fonctions Mocks

vi

expect

expectTypeOf

assert

assertType

Guide

Interface en ligne de commande (CLI)

Filtrage des tests

Projets de Test

Rapporteurs

Couverture de code

Instantanés

Simulation

Parallélisme

Tests de type

Interface utilisateur de Vitest

Tests in-source

Contexte de test

Annotations de test

Environnement de Test

Étendre les Matchers

Intégrations IDE

Débogage

Erreurs courantes

Guide de migration

Migration vers Vitest 3.0

Migration depuis Jest

Performance

Analyse des performances des tests

Amélioration des performances

Mode Navigateur

API avancée

Comparaison avec d'autres exécuteurs de tests

Sur cette page

Simulation ​

Lors de la rédaction de tests, il est souvent nécessaire de créer une version "fictive" d'un service, qu'il soit interne ou externe. C'est ce que l'on appelle communément le mocking (ou simulation). Vitest met à votre disposition des fonctions utilitaires via son module vi. Vous pouvez l'importer depuis vitest ou y accéder globalement si la configuration globals est activée.

WARNING

N'oubliez jamais de réinitialiser ou de restaurer les mocks avant ou après chaque test afin d'annuler les modifications d'état des mocks entre les exécutions. Pour plus d'informations, consultez la documentation de mockReset.

Si vous n'êtes pas familier avec les méthodes vi.fn, vi.mock ou vi.spyOn, veuillez consulter la section API au préalable.

Dates ​

Il est parfois nécessaire de contrôler la date pour garantir la cohérence des tests. Vitest utilise le package @sinonjs/fake-timers pour manipuler les minuteurs et la date système. Vous trouverez plus de détails sur l'API spécifique ici.

Exemple ​

js
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';

const businessHours = [9, 17];

function purchase() {
  const currentHour = new Date().getHours();
  const [open, close] = businessHours;

  if (currentHour > open && currentHour < close) {
    return { message: 'Success' };
  }

  return { message: 'Error' };
}

describe('purchasing flow', () => {
  beforeEach(() => {
    // Indiquer à Vitest que nous utilisons le temps simulé
    vi.useFakeTimers();
  });

  afterEach(() => {
    // Restaurer la date après chaque exécution de test
    vi.useRealTimers();
  });

  it('allows purchases within business hours', () => {
    // Définir l'heure pendant les heures ouvrables
    const date = new Date(2000, 1, 1, 13);
    vi.setSystemTime(date);

    // L'accès à Date.now() renverra la date définie ci-dessus
    expect(purchase()).toEqual({ message: 'Success' });
  });

  it('disallows purchases outside of business hours', () => {
    // Définir l'heure en dehors des heures ouvrables
    const date = new Date(2000, 1, 1, 19);
    vi.setSystemTime(date);

    // L'accès à Date.now() renverra la date définie ci-dessus
    expect(purchase()).toEqual({ message: 'Error' });
  });
});

Fonctions ​

La simulation de fonctions peut être divisée en deux catégories : l'espionnage et la simulation.

Parfois, il suffit de valider si une fonction spécifique a été appelée (et éventuellement avec quels arguments). Dans ces cas, un espion est suffisant, que vous pouvez utiliser directement avec vi.spyOn() ([pour plus d'informations, consultez ici]).

Cependant, les espions ne peuvent que vous aider à espionner les fonctions ; ils ne sont pas capables de modifier leur implémentation. Dans le cas où nous devons créer une version fictive (ou simulée) d'une fonction, nous pouvons utiliser vi.fn() ([pour plus d'informations, consultez ici]).

Nous utilisons Tinyspy comme base pour la simulation de fonctions, mais nous avons notre propre wrapper pour assurer la compatibilité avec jest. Les méthodes vi.fn() et vi.spyOn() partagent les mêmes méthodes, cependant seul le résultat de vi.fn() peut être appelé.

Exemple ​

js
import { afterEach, describe, expect, it, vi } from 'vitest';

const messages = {
  items: [
    { message: 'Simple test message', from: 'Testman' },
    // ...
  ],
  getLatest, // peut également être un accesseur (getter) ou un mutateur (setter) si pris en charge
};

function getLatest(index = messages.items.length - 1) {
  return messages.items[index];
}

describe('reading messages', () => {
  afterEach(() => {
    vi.restoreAllMocks();
  });

  it('should get the latest message with a spy', () => {
    const spy = vi.spyOn(messages, 'getLatest');
    expect(spy.getMockName()).toEqual('getLatest');

    expect(messages.getLatest()).toEqual(
      messages.items[messages.items.length - 1]
    );

    expect(spy).toHaveBeenCalledTimes(1);

    spy.mockImplementationOnce(() => 'access-restricted');
    expect(messages.getLatest()).toEqual('access-restricted');

    expect(spy).toHaveBeenCalledTimes(2);
  });

  it('should get with a mock', () => {
    const mock = vi.fn().mockImplementation(getLatest);

    expect(mock()).toEqual(messages.items[messages.items.length - 1]);
    expect(mock).toHaveBeenCalledTimes(1);

    mock.mockImplementationOnce(() => 'access-restricted');
    expect(mock()).toEqual('access-restricted');

    expect(mock).toHaveBeenCalledTimes(2);

    expect(mock()).toEqual(messages.items[messages.items.length - 1]);
    expect(mock).toHaveBeenCalledTimes(3);
  });
});

Plus ​

  • Fonctions de simulation de Jest

Variables globales ​

Vous pouvez simuler des variables globales qui ne sont pas présentes avec jsdom ou node en utilisant l'utilitaire vi.stubGlobal. Cela placera la valeur de la variable globale dans l'objet globalThis.

ts
import { vi } from 'vitest';

const IntersectionObserverMock = vi.fn(() => ({
  disconnect: vi.fn(),
  observe: vi.fn(),
  takeRecords: vi.fn(),
  unobserve: vi.fn(),
}));

vi.stubGlobal('IntersectionObserver', IntersectionObserverMock);

// vous pouvez maintenant y accéder en tant que `IntersectionObserver` ou `window.IntersectionObserver`

Modules ​

La simulation de modules permet d'intercepter les bibliothèques tierces invoquées dans d'autres parties du code, vous permettant ainsi de tester les arguments, la sortie ou même de redéfinir leur implémentation.

Consultez la section API de vi.mock() pour une description plus détaillée de l'API.

Algorithme d'auto-simulation ​

Si votre code importe un module simulé, sans aucun fichier __mocks__ associé ou factory pour ce module, Vitest simulera le module lui-même en l'invoquant et en simulant chaque exportation.

Les principes suivants s'appliquent :

  • Tous les tableaux seront rendus vides.
  • Toutes les primitives et collections resteront inchangées.
  • Tous les objets seront clonés en profondeur.
  • Toutes les instances de classes et leurs prototypes seront clonés en profondeur.

Modules virtuels ​

Vitest prend en charge la simulation des modules virtuels de Vite. Cela fonctionne différemment de la façon dont les modules virtuels sont traités dans Jest. Au lieu de passer virtual: true à une fonction vi.mock, vous devez indiquer à Vite que le module existe, sinon il échouera lors de l'analyse. Vous pouvez le faire de plusieurs manières :

  1. Fournir un alias
ts
import { defineConfig } from 'vitest/config';
import { resolve } from 'node:path';
export default defineConfig({
  test: {
    alias: {
      '$app/forms': resolve('./mocks/forms.js'),
    },
  },
});
  1. Fournir un plugin qui résout un module virtuel
ts
import { defineConfig } from 'vitest/config';
export default defineConfig({
  plugins: [
    {
      name: 'virtual-modules',
      resolveId(id) {
        if (id === '$app/forms') {
          return 'virtual:$app/forms';
        }
      },
    },
  ],
});

L'avantage de la deuxième approche est que vous pouvez créer dynamiquement différents points d'entrée virtuels. Si vous redirigez plusieurs modules virtuels vers un seul fichier, tous seront impactés par vi.mock, alors assurez-vous d'utiliser des identifiants uniques.

Pièges de la simulation ​

Sachez qu'il n'est pas possible de simuler les appels aux méthodes qui sont invoquées par d'autres méthodes du même fichier. Par exemple, dans ce code :

ts
export function foo() {
  return 'foo';
}

export function foobar() {
  return `${foo()}bar`;
}

Il n'est pas possible de simuler la méthode foo de l'extérieur car elle est référencée directement. Ainsi, ce code n'aura aucun effet sur l'appel de foo à l'intérieur de foobar (mais il affectera l'appel de foo dans d'autres modules) :

ts
import { vi } from 'vitest';
import * as mod from './foobar.js';

// cela n'affectera "foo" qu'en dehors du module original
vi.spyOn(mod, 'foo');
vi.mock('./foobar.js', async importOriginal => {
  return {
    ...(await importOriginal<typeof import('./foobar.js')>()),
    // cela n'affectera "foo" qu'en dehors du module original
    foo: () => 'mocked',
  };
});

Vous pouvez confirmer ce comportement en fournissant directement l'implémentation à la méthode foobar :

ts
import * as mod from './foobar.js';

vi.spyOn(mod, 'foo');

// foo exporté référence la méthode simulée
mod.foobar(mod.foo);
ts
export function foo() {
  return 'foo';
}

export function foobar(injectedFoo) {
  return injectedFoo === foo; // false
}

C'est le comportement attendu. Cela indique généralement une mauvaise pratique de codage lorsque la simulation est utilisée de cette manière. Envisagez de refactoriser votre code en plusieurs fichiers ou d'améliorer l'architecture de votre application en utilisant des techniques telles que l'injection de dépendances.

Exemple ​

js
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
import { Client } from 'pg';
import { failure, success } from './handlers.js';

// obtenir les tâches
export async function getTodos(event, context) {
  const client = new Client({
    // ...clientOptions
  });

  await client.connect();

  try {
    const result = await client.query('SELECT * FROM todos;');

    client.end();

    return success({
      message: `${result.rowCount} item(s) returned`,
      data: result.rows,
      status: true,
    });
  } catch (e) {
    console.error(e.stack);

    client.end();

    return failure({ message: e, status: false });
  }
}

vi.mock('pg', () => {
  const Client = vi.fn();
  Client.prototype.connect = vi.fn();
  Client.prototype.query = vi.fn();
  Client.prototype.end = vi.fn();

  return { Client };
});

vi.mock('./handlers.js', () => {
  return {
    success: vi.fn(),
    failure: vi.fn(),
  };
});

describe('get a list of todo items', () => {
  let client;

  beforeEach(() => {
    client = new Client();
  });

  afterEach(() => {
    vi.clearAllMocks();
  });

  it('should return items successfully', async () => {
    client.query.mockResolvedValueOnce({ rows: [], rowCount: 0 });

    await getTodos();

    expect(client.connect).toBeCalledTimes(1);
    expect(client.query).toBeCalledWith('SELECT * FROM todos;');
    expect(client.end).toBeCalledTimes(1);

    expect(success).toBeCalledWith({
      message: '0 item(s) returned',
      data: [],
      status: true,
    });
  });

  it('should throw an error', async () => {
    const mError = new Error('Unable to retrieve rows');
    client.query.mockRejectedValueOnce(mError);

    await getTodos();

    expect(client.connect).toBeCalledTimes(1);
    expect(client.query).toBeCalledWith('SELECT * FROM todos;');
    expect(client.end).toBeCalledTimes(1);
    expect(failure).toBeCalledWith({ message: mError, status: false });
  });
});

Système de fichiers ​

La simulation du système de fichiers garantit que les tests ne dépendent pas du système de fichiers réel, les rendant ainsi plus fiables et prévisibles. Cette isolation permet d'éviter les effets secondaires des tests précédents. Elle permet de tester des conditions d'erreur et des cas limites qui pourraient être difficiles ou impossibles à reproduire avec un système de fichiers réel, tels que des problèmes de permissions, des scénarios de disque saturé ou des erreurs de lecture/écriture.

Vitest ne fournit aucune API de simulation de système de fichiers nativement. Vous pouvez utiliser vi.mock pour simuler le module fs manuellement, mais cela est difficile à maintenir. Au lieu de cela, nous vous recommandons d'utiliser memfs pour le faire à votre place. memfs crée un système de fichiers en mémoire, qui simule les opérations du système de fichiers sans toucher le disque réel. Cette approche est rapide et sûre, évitant ainsi tout effet secondaire potentiel sur le système de fichiers réel.

Exemple ​

Pour rediriger automatiquement chaque appel fs vers memfs, vous pouvez créer les fichiers __mocks__/fs.cjs et __mocks__/fs/promises.cjs à la racine de votre projet :

ts
// nous pouvons aussi utiliser `import`, mais alors
// chaque exportation devrait être explicitement définie

const { fs } = require('memfs');
module.exports = fs;
ts
// nous pouvons aussi utiliser `import`, mais alors
// chaque exportation devrait être explicitement définie

const { fs } = require('memfs');
module.exports = fs.promises;
ts
import { readFileSync } from 'node:fs';

export function readHelloWorld(path) {
  return readFileSync(path, 'utf-8');
}
ts
import { beforeEach, expect, it, vi } from 'vitest';
import { fs, vol } from 'memfs';
import { readHelloWorld } from './read-hello-world.js';

// indiquer à Vitest d'utiliser la simulation du module fs du dossier __mocks__
// cela peut être fait dans un fichier de configuration si fs doit toujours être simulé
vi.mock('node:fs');
vi.mock('node:fs/promises');

beforeEach(() => {
  // réinitialiser l'état du système de fichiers en mémoire
  vol.reset();
});

it('should return correct text', () => {
  const path = '/hello-world.txt';
  fs.writeFileSync(path, 'hello world');

  const text = readHelloWorld(path);
  expect(text).toBe('hello world');
});

it('can return a value multiple times', () => {
  // vous pouvez utiliser vol.fromJSON pour définir plusieurs fichiers
  vol.fromJSON(
    {
      './dir1/hw.txt': 'hello dir1',
      './dir2/hw.txt': 'hello dir2',
    },
    // répertoire de travail par défaut
    '/tmp'
  );

  expect(readHelloWorld('/tmp/dir1/hw.txt')).toBe('hello dir1');
  expect(readHelloWorld('/tmp/dir2/hw.txt')).toBe('hello dir2');
});

Requêtes ​

Étant donné que Vitest s'exécute dans Node.js, la simulation des requêtes réseau est délicate ; les API web ne sont pas disponibles, nous avons donc besoin d'un outil qui simulera le comportement réseau. Nous recommandons Mock Service Worker pour y parvenir. Il vous permet de simuler les requêtes réseau http, WebSocket et GraphQL, et est indépendant du framework.

Mock Service Worker (MSW) fonctionne en interceptant les requêtes que vos tests effectuent, ce qui permet de l'utiliser sans modifier votre code d'application. Dans le navigateur, cela utilise l'API Service Worker. Dans Node.js (et pour Vitest), il utilise la bibliothèque @mswjs/interceptors. Pour en savoir plus sur MSW, lisez leur introduction

Configuration ​

Vous pouvez l'utiliser de la manière suivante dans votre fichier de configuration :

js
import { afterAll, afterEach, beforeAll } from 'vitest';
import { setupServer } from 'msw/node';
import { http, HttpResponse } from 'msw';

const posts = [
  {
    userId: 1,
    id: 1,
    title: 'first post title',
    body: 'first post body',
  },
  // ...
];

export const restHandlers = [
  http.get('https://rest-endpoint.example/path/to/posts', () => {
    return HttpResponse.json(posts);
  }),
];

const server = setupServer(...restHandlers);

// Démarrer le serveur avant tous les tests
beforeAll(() => server.listen({ onUnhandledRequest: 'error' }));

// Fermer le serveur après tous les tests
afterAll(() => server.close());

// Réinitialiser les gestionnaires après chaque test pour assurer l'isolation des tests
afterEach(() => server.resetHandlers());
js
import { afterAll, afterEach, beforeAll } from 'vitest';
import { setupServer } from 'msw/node';
import { graphql, HttpResponse } from 'msw';

const posts = [
  {
    userId: 1,
    id: 1,
    title: 'first post title',
    body: 'first post body',
  },
  // ...
];

const graphqlHandlers = [
  graphql.query('ListPosts', () => {
    return HttpResponse.json({
      data: { posts },
    });
  }),
];

const server = setupServer(...graphqlHandlers);

// Démarrer le serveur avant tous les tests
beforeAll(() => server.listen({ onUnhandledRequest: 'error' }));

// Fermer le serveur après tous les tests
afterAll(() => server.close());

// Réinitialiser les gestionnaires après chaque test pour assurer l'isolation des tests
afterEach(() => server.resetHandlers());
js
import { afterAll, afterEach, beforeAll } from 'vitest';
import { setupServer } from 'msw/node';
import { ws } from 'msw';

const chat = ws.link('wss://chat.example.com');

const wsHandlers = [
  chat.addEventListener('connection', ({ client }) => {
    client.addEventListener('message', event => {
      console.log('Received message from client:', event.data);
      // Renvoyer le message reçu au client
      client.send(`Server received: ${event.data}`);
    });
  }),
];

const server = setupServer(...wsHandlers);

// Démarrer le serveur avant tous les tests
beforeAll(() => server.listen({ onUnhandledRequest: 'error' }));

// Fermer le serveur après tous les tests
afterAll(() => server.close());

// Réinitialiser les gestionnaires après chaque test pour assurer l'isolation des tests
afterEach(() => server.resetHandlers());

La configuration du serveur avec onUnhandledRequest: 'error' garantit qu'une erreur est levée chaque fois qu'une requête n'a pas de gestionnaire correspondant.

Plus ​

MSW offre de nombreuses autres possibilités. Vous pouvez accéder aux cookies et aux paramètres de requête, définir des réponses d'erreur simulées, et bien plus encore ! Pour voir tout ce que vous pouvez faire avec MSW, lisez leur documentation.

Minuteurs ​

Lorsque nous testons du code qui implique des délais d'attente ou des intervalles, au lieu de laisser nos tests attendre ou dépasser le délai, nous pouvons accélérer nos tests en utilisant des minuteurs "fictifs" qui simulent les appels à setTimeout et setInterval.

Consultez la section API de vi.useFakeTimers pour une description plus détaillée de l'API.

Exemple ​

js
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';

function executeAfterTwoHours(func) {
  setTimeout(func, 1000 * 60 * 60 * 2); // 2 heures
}

function executeEveryMinute(func) {
  setInterval(func, 1000 * 60); // 1 minute
}

const mock = vi.fn(() => console.log('executed'));

describe('delayed execution', () => {
  beforeEach(() => {
    vi.useFakeTimers();
  });
  afterEach(() => {
    vi.restoreAllMocks();
  });
  it('should execute the function', () => {
    executeAfterTwoHours(mock);
    vi.runAllTimers();
    expect(mock).toHaveBeenCalledTimes(1);
  });
  it('should not execute the function', () => {
    executeAfterTwoHours(mock);
    // avancer de 2ms ne déclenchera pas l'exécution de la fonction
    vi.advanceTimersByTime(2);
    expect(mock).not.toHaveBeenCalled();
  });
  it('should execute every minute', () => {
    executeEveryMinute(mock);
    vi.advanceTimersToNextTimer();
    expect(mock).toHaveBeenCalledTimes(1);
    vi.advanceTimersToNextTimer();
    expect(mock).toHaveBeenCalledTimes(2);
  });
});

Classes ​

Vous pouvez simuler une classe entière avec un seul appel vi.fn – puisque toutes les classes sont aussi des fonctions, cela fonctionne nativement. Sachez qu'actuellement Vitest ne prend pas en charge le mot-clé new, donc new.target est toujours undefined dans le corps d'une fonction.

ts
class Dog {
  name: string;

  constructor(name: string) {
    this.name = name;
  }

  static getType(): string {
    return 'animal';
  }

  greet = (): string => {
    return `Hi! My name is ${this.name}!`;
  };

  speak(): string {
    return 'bark!';
  }

  isHungry() {}
  feed() {}
}

Nous pouvons recréer cette classe avec des fonctions ES5 :

ts
const Dog = vi.fn(function (name) {
  this.name = name;
  // simuler les méthodes d'instance dans le constructeur, chaque instance aura son propre espion
  this.greet = vi.fn(() => `Hi! My name is ${this.name}!`);
});

// notez que les méthodes statiques sont simulées directement sur la fonction,
// et non sur l'instance de la classe
Dog.getType = vi.fn(() => 'mocked animal');

// simuler les méthodes "speak" et "feed" sur chaque instance d'une classe
// toutes les instances `new Dog()` hériteront et partageront ces espions
Dog.prototype.speak = vi.fn(() => 'loud bark!');
Dog.prototype.feed = vi.fn();

WARNING

Si une valeur non primitive est renvoyée par la fonction constructeur, cette valeur deviendra le résultat de la nouvelle expression. Dans ce cas, le [[Prototype]] peut ne pas être correctement associé :

ts
const CorrectDogClass = vi.fn(function (name) {
  this.name = name;
});

const IncorrectDogClass = vi.fn(name => ({
  name,
}));

const Marti = new CorrectDogClass('Marti');
const Newt = new IncorrectDogClass('Newt');

Marti instanceof CorrectDogClass; // ✅ true
Newt instanceof IncorrectDogClass; // ❌ false!

QUAND L'UTILISER ?

Généralement, vous recréeriez une classe comme celle-ci à l'intérieur de la fabrique de modules si la classe est réexportée depuis un autre module :

ts
import { Dog } from './dog.js';

vi.mock(import('./dog.js'), () => {
  const Dog = vi.fn();
  Dog.prototype.feed = vi.fn();
  // ... autres mocks
  return { Dog };
});

Cette méthode peut également être utilisée pour passer une instance d'une classe à une fonction qui implémente la même interface :

ts
function feed(dog: Dog) {
  // ...
}
ts
import { expect, test, vi } from 'vitest';
import { feed } from '../src/feed.js';

const Dog = vi.fn();
Dog.prototype.feed = vi.fn();

test('can feed dogs', () => {
  const dogMax = new Dog('Max');

  feed(dogMax);

  expect(dogMax.feed).toHaveBeenCalled();
  expect(dogMax.isHungry()).toBe(false);
});

Maintenant, lorsque nous créons une nouvelle instance de la classe Dog, sa méthode speak (ainsi que feed et greet) est déjà simulée :

ts
const Cooper = new Dog('Cooper');
Cooper.speak(); // loud bark!
Cooper.greet(); // Hi! My name is Cooper!

// vous pouvez utiliser les assertions intégrées pour vérifier la validité de l'appel
expect(Cooper.speak).toHaveBeenCalled();
expect(Cooper.greet).toHaveBeenCalled();

const Max = new Dog('Max');

// les méthodes assignées au prototype sont partagées entre les instances
expect(Max.speak).toHaveBeenCalled();
expect(Max.greet).not.toHaveBeenCalled();

Nous pouvons réaffecter la valeur de retour pour une instance spécifique :

ts
const dog = new Dog('Cooper');

// "vi.mocked" est un utilitaire de typage, car
// TypeScript ne sait pas que Dog est une classe simulée,
// il enveloppe toute fonction dans un type MockInstance<T>
// sans valider si la fonction est une simulation
vi.mocked(dog.speak).mockReturnValue('woof woof');

dog.speak(); // woof woof

Pour simuler la propriété, nous pouvons utiliser la méthode vi.spyOn(dog, 'name', 'get'). Cela permet d'utiliser des assertions d'espion sur la propriété simulée :

ts
const dog = new Dog('Cooper');

const nameSpy = vi.spyOn(dog, 'name', 'get').mockReturnValue('Max');

expect(dog.name).toBe('Max');
expect(nameSpy).toHaveBeenCalledTimes(1);

TIP

Vous pouvez également espionner les accesseurs (getters) et les mutateurs (setters) en utilisant la même méthode.

Aide-mémoire ​

INFO

vi dans les exemples ci-dessous est importé directement de vitest. Vous pouvez également l'utiliser globalement, si vous activez l'option globals en la définissant à true dans votre configuration.

Je veux…

Simuler des variables exportées ​

js
export const getter = 'variable';
ts
import * as exports from './example.js';

vi.spyOn(exports, 'getter', 'get').mockReturnValue('mocked');

Simuler une fonction exportée ​

  1. Exemple avec vi.mock :

WARNING

N'oubliez pas qu'un appel vi.mock est remonté en haut du fichier (hoisted). Il sera toujours exécuté avant toutes les importations.

ts
export function method() {}
ts
import { method } from './example.js';

vi.mock('./example.js', () => ({
  method: vi.fn(),
}));
  1. Exemple avec vi.spyOn :
ts
import * as exports from './example.js';

vi.spyOn(exports, 'method').mockImplementation(() => {});

Simuler l'implémentation d'une classe exportée ​

  1. Exemple avec vi.mock et .prototype :
ts
export class SomeClass {}
ts
import { SomeClass } from './example.js';

vi.mock(import('./example.js'), () => {
  const SomeClass = vi.fn();
  SomeClass.prototype.someMethod = vi.fn();
  return { SomeClass };
});
// SomeClass.mock.instances aura SomeClass
  1. Exemple avec vi.spyOn :
ts
import * as mod from './example.js';

const SomeClass = vi.fn();
SomeClass.prototype.someMethod = vi.fn();

vi.spyOn(mod, 'SomeClass').mockImplementation(SomeClass);

Espionner un objet retourné par une fonction ​

  1. Exemple utilisant le cache :
ts
export function useObject() {
  return { method: () => true };
}
ts
import { useObject } from './example.js';

const obj = useObject();
obj.method();
ts
import { useObject } from './example.js';

vi.mock(import('./example.js'), () => {
  let _cache;
  const useObject = () => {
    if (!_cache) {
      _cache = {
        method: vi.fn(),
      };
    }
    // maintenant, chaque fois que useObject() est appelé, il retournera la même référence d'objet
    return _cache;
  };
  return { useObject };
});

const obj = useObject();
// obj.method a été appelé à l'intérieur de some-path
expect(obj.method).toHaveBeenCalled();

Simuler une partie d'un module ​

ts
import { mocked, original } from './some-path.js';

vi.mock(import('./some-path.js'), async importOriginal => {
  const mod = await importOriginal();
  return {
    ...mod,
    mocked: vi.fn(),
  };
});
original(); // a le comportement original
mocked(); // est une fonction espionne

WARNING

N'oubliez pas que cela ne simule que l'accès externe. Dans cet exemple, si original appelle mocked en interne, il appellera toujours la fonction définie dans le module, et non dans la fabrique de mocks.

Simuler la date actuelle ​

Pour simuler l'heure de Date, vous pouvez utiliser la fonction d'aide vi.setSystemTime. Cette valeur ne sera pas automatiquement réinitialisée entre les tests.

Sachez que l'utilisation de vi.useFakeTimers modifie également l'heure de l'objet Date.

ts
const mockDate = new Date(2022, 0, 1);
vi.setSystemTime(mockDate);
const now = new Date();
expect(now.valueOf()).toBe(mockDate.valueOf());
// réinitialiser le temps simulé
vi.useRealTimers();

Simuler une variable globale ​

Vous pouvez définir une variable globale en assignant une valeur à globalThis ou en utilisant l'utilitaire vi.stubGlobal. Lorsque vous utilisez vi.stubGlobal, elle ne sera pas automatiquement réinitialisée entre les tests, sauf si vous activez l'option de configuration unstubGlobals ou appelez vi.unstubAllGlobals.

ts
vi.stubGlobal('__VERSION__', '1.0.0');
expect(__VERSION__).toBe('1.0.0');

Simuler import.meta.env ​

  1. Pour modifier une variable d'environnement, vous pouvez simplement lui assigner une nouvelle valeur.

WARNING

La valeur de la variable d'environnement ne sera pas automatiquement réinitialisée entre les tests.

ts
import { beforeEach, expect, it } from 'vitest';

// avant d'exécuter les tests, "VITE_ENV" est à "test"
const originalViteEnv = import.meta.env.VITE_ENV;

beforeEach(() => {
  import.meta.env.VITE_ENV = originalViteEnv;
});

it('changes value', () => {
  import.meta.env.VITE_ENV = 'staging';
  expect(import.meta.env.VITE_ENV).toBe('staging');
});
  1. Si vous souhaitez réinitialiser automatiquement la ou les valeurs, vous pouvez utiliser l'utilitaire vi.stubEnv avec l'option de configuration unstubEnvs activée (ou appeler vi.unstubAllEnvs manuellement dans un hook beforeEach) :
ts
import { expect, it, vi } from 'vitest';

// avant d'exécuter les tests, "VITE_ENV" est à "test"
import.meta.env.VITE_ENV === 'test';

it('changes value', () => {
  vi.stubEnv('VITE_ENV', 'staging');
  expect(import.meta.env.VITE_ENV).toBe('staging');
});

it('the value is restored before running an other test', () => {
  expect(import.meta.env.VITE_ENV).toBe('test');
});
ts
export default defineConfig({
  test: {
    unstubEnvs: true,
  },
});
Pager
Page précédenteInstantanés
Page suivanteParallélisme

Publié sous la licence MIT.

Copyright (c) 2021-Present Vitest Team

https://vitest.dev/guide/mocking

Publié sous la licence MIT.

Copyright (c) 2021-Present Vitest Team