Skip to content
Vitest 3
Main Navigation Leitfaden & APIKonfigurationBrowser-ModusFortgeschritten API
3.2.0
2.1.9
1.6.1
0.34.6

Deutsch

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

Deutsch

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

Aussehen

Sidebar Navigation

Einführung

Warum Vitest

Erste Schritte

Funktionen

Vitest konfigurieren

API

Test-API-Referenz

Mock-Funktionen

Vi

expect

expectTypeOf

assert

assertType

Leitfaden

Befehlszeilenschnittstelle

Testfilterung

Testprojekte

Reporter

Code-Abdeckung

Snapshot

Mocking

Parallelisierung

Typüberprüfungen

Vitest UI

Tests im Quellcode

Test-Kontext

Test-Annotationen

Testumgebung

Matcher erweitern

IDE-Integrationen

Debugging

Häufige Fehler

Migrationsleitfaden

Migration zu Vitest 3.0

Migration von Jest

Performance

Leistungsprofilierung von Tests

Leistung verbessern

Browser-Modus

Erweiterte API

Vergleiche mit anderen Test-Runnern

Auf dieser Seite

Vi ​

Vitest stellt Hilfsfunktionen über den vi-Helfer bereit. Sie können global darauf zugreifen (sofern die globale Konfiguration aktiviert ist) oder ihn direkt von vitest importieren:

js
import { vi } from 'vitest';

Module mocken ​

Dieser Abschnitt beschreibt die API zum Mocken von Modulen. Beachten Sie, dass Vitest das Mocken von Modulen, die mit require() importiert wurden, nicht unterstützt.

vi.mock ​

  • Typ: (path: string, factory?: MockOptions | ((importOriginal: () => unknown) => unknown)) => void
  • Typ: <T>(path: Promise<T>, factory?: MockOptions | ((importOriginal: () => T) => T | Promise<T>)) => void

Ersetzt alle Importe, die vom angegebenen path stammen, durch ein anderes Modul. Sie können konfigurierte Vite-Aliase innerhalb eines Pfades verwenden. Der Aufruf von vi.mock wird hochgezogen (hoisted), d.h. er wird immer vor allen Importen ausgeführt, unabhängig davon, wo Sie ihn aufrufen. Wenn Sie auf Variablen zugreifen müssen, die außerhalb seines Geltungsbereichs definiert sind, können Sie diese innerhalb von vi.hoisted definieren und innerhalb von vi.mock darauf verweisen.

WARNING

vi.mock funktioniert nur für Module, die mit dem import-Schlüsselwort importiert wurden. Es funktioniert nicht mit require.

Um vi.mock hochzuziehen, analysiert Vitest Ihre Dateien statisch. Dies bedeutet, dass ein vi-Objekt, das nicht direkt aus dem vitest-Paket importiert wurde (z. B. aus einer Hilfsdatei), nicht verwendet werden kann. Verwenden Sie vi.mock mit vi, das von vitest importiert wurde, oder aktivieren Sie die Konfigurationsoption globals.

Vitest mockt keine Module, die in einer Setup-Datei importiert wurden, da sie zum Zeitpunkt der Ausführung einer Testdatei bereits zwischengespeichert sind. Sie können vi.resetModules() innerhalb von vi.hoisted aufrufen, um alle Modul-Caches vor der Ausführung einer Testdatei zu leeren.

Wenn die factory-Funktion definiert ist, geben alle Importe ihr Ergebnis zurück. Vitest ruft die Factory nur einmal auf und speichert die Ergebnisse für alle nachfolgenden Importe im Cache, bis vi.unmock oder vi.doUnmock aufgerufen wird.

Im Gegensatz zu Jest kann die Factory asynchron sein. Sie können vi.importActual oder einen Helfer verwenden, indem Sie die Factory als erstes Argument übergeben, um das ursprüngliche Modul darin zu erhalten.

Sie können auch ein Objekt mit einer spy-Eigenschaft anstelle einer Factory-Funktion bereitstellen. Wenn spy true ist, wird Vitest das Modul wie gewohnt automocken, dabei aber die Implementierung der Exporte nicht überschreiben. Dies ist nützlich, um zu überprüfen, ob die exportierte Methode korrekt von einer anderen Methode aufgerufen wurde.

ts
import { calculator } from './src/calculator.ts';

vi.mock('./src/calculator.ts', { spy: true });

// ruft die ursprüngliche Implementierung auf,
// ermöglicht aber später die Überprüfung des Verhaltens
const result = calculator(1, 2);

expect(result).toBe(3);
expect(calculator).toHaveBeenCalledWith(1, 2);
expect(calculator).toHaveReturned(3);

Vitest unterstützt auch ein Promise eines Moduls anstelle eines Strings in den Methoden vi.mock und vi.doMock für eine bessere IDE-Unterstützung. Wenn die Datei verschoben wird, wird der Pfad aktualisiert, wobei importOriginal den Typ automatisch erbt. Die Verwendung dieser Signatur erzwingt auch, dass der Rückgabetyp der Factory mit dem ursprünglichen Modul kompatibel ist (wobei Exporte optional bleiben).

ts
// @filename: ./path/to/module.js
export declare function total(...numbers: number[]): number;
// @filename: test.js
import { vi } from 'vitest';
// ---cut---
vi.mock(import('./path/to/module.js'), async importOriginal => {
  const mod = await importOriginal(); // Typ wird abgeleitet
  //    ^?
  return {
    ...mod,
    // einige Exporte ersetzen
    total: vi.fn(),
  };
});

Intern arbeitet Vitest immer noch mit einem String und nicht mit einem Modulobjekt.

Wenn Sie jedoch TypeScript mit in tsconfig.json konfigurierten Pfad-Aliasen verwenden, kann der Compiler die Importtypen nicht korrekt auflösen. Damit dies funktioniert, stellen Sie sicher, dass alle aliased Imports durch ihre entsprechenden relativen Pfade ersetzt werden. Z.B. verwenden Sie import('./path/to/module.js') anstelle von import('@/module').

WARNING

vi.mock wird an den Anfang der Datei hochgezogen (mit anderen Worten, verschoben). Das bedeutet, dass es immer dann aufgerufen wird, wenn Sie es schreiben (sei es innerhalb von beforeEach oder test), tatsächlich vorher aufgerufen wird.

Das bedeutet auch, dass Sie innerhalb der Factory keine Variablen verwenden können, die außerhalb der Factory definiert sind.

Wenn Sie Variablen in der Factory verwenden müssen, versuchen Sie vi.doMock. Es funktioniert auf die gleiche Weise, wird aber nicht hochgezogen. Beachten Sie, dass es nur nachfolgende Importe mockt.

Sie können auch auf Variablen verweisen, die von der vi.hoisted-Methode definiert wurden, wenn sie vor vi.mock deklariert wurde:

ts
import { namedExport } from './path/to/module.js';

const mocks = vi.hoisted(() => {
  return {
    namedExport: vi.fn(),
  };
});

vi.mock('./path/to/module.js', () => {
  return {
    namedExport: mocks.namedExport,
  };
});

vi.mocked(namedExport).mockReturnValue(100);

expect(namedExport()).toBe(100);
expect(namedExport).toBe(mocks.namedExport);

WARNING

Wenn Sie ein Modul mit einem Standardexport mocken möchten, müssen Sie einen default-Schlüssel innerhalb des zurückgegebenen Factory-Funktionsobjekts bereitstellen. Dies ist eine ES-Modul-spezifische Besonderheit; daher kann die Jest-Dokumentation abweichen, da Jest CommonJS-Module verwendet. Zum Beispiel:

ts
vi.mock('./path/to/module.js', () => {
  return {
    default: { myDefaultKey: vi.fn() },
    namedExport: vi.fn(),
    // etc...
  };
});

Wenn sich ein __mocks__-Ordner neben einer Datei befindet, die Sie mocken, und keine Factory bereitgestellt wird, versucht Vitest, eine Datei mit demselben Namen im Unterordner __mocks__ zu finden und diese als tatsächliches Modul zu verwenden. Wenn Sie eine Abhängigkeit mocken, versucht Vitest, einen __mocks__-Ordner im Stammverzeichnis des Projekts zu finden (Standard ist process.cwd()). Über die Konfigurationsoption deps.moduleDirectories können Sie Vitest mitteilen, wo sich die Abhängigkeiten befinden.

Sie haben zum Beispiel diese Dateistruktur:

- __mocks__
  - axios.js
- src
  __mocks__
    - increment.js
  - increment.js
- tests
  - increment.test.js

Wenn Sie vi.mock in einer Testdatei ohne Factory oder Optionen aufrufen, findet es eine Datei im __mocks__-Ordner, die als Modul verwendet werden soll:

ts
import { vi } from 'vitest';

// axios ist ein Standardexport aus `__mocks__/axios.js`
import axios from 'axios';

// increment ist ein benannter Export aus `src/__mocks__/increment.js`
import { increment } from '../increment.js';

vi.mock('axios');
vi.mock('../increment.js');

axios.get(`/apples/${increment(1)}`);

WARNING

Beachten Sie, dass Module nicht automatisch gemockt werden, wenn vi.mock nicht aufgerufen wird. Um das Automocking-Verhalten von Jest nachzubilden, können Sie vi.mock für jedes erforderliche Modul innerhalb von setupFiles aufrufen.

Wenn weder ein __mocks__-Ordner noch eine Factory bereitgestellt wird, importiert Vitest das ursprüngliche Modul und automockt alle seine Exporte. Die angewendeten Regeln finden Sie unter Algorithmus.

vi.doMock ​

  • Typ: (path: string, factory?: MockOptions | ((importOriginal: () => unknown) => unknown)) => void
  • Typ: <T>(path: Promise<T>, factory?: MockOptions | ((importOriginal: () => T) => T | Promise<T>)) => void

Dasselbe wie vi.mock, aber es wird nicht an den Anfang der Datei hochgezogen, sodass Sie auf Variablen im globalen Dateibereich verweisen können. Das Modul wird beim nächsten dynamischen Import gemockt.

WARNING

Dies mockt keine Module, die vor diesem Aufruf importiert wurden. Vergessen Sie nicht, dass alle statischen Importe in ESM immer hochgezogen werden, sodass das Platzieren dieses vor einem statischen Import nicht erzwingt, dass es vor dem Import aufgerufen wird:

ts
vi.doMock('./increment.js'); // dieser Aufruf wird _nach_ der Importanweisung aufgerufen

import { increment } from './increment.js';
ts
export function increment(number) {
  return number + 1;
}
ts
import { beforeEach, test } from 'vitest';
import { increment } from './increment.js';

// das Modul ist nicht gemockt, da vi.doMock noch nicht aufgerufen wurde
increment(1) === 2;

let mockedIncrement = 100;

beforeEach(() => {
  // Sie können auf Variablen innerhalb einer Factory zugreifen
  vi.doMock('./increment.js', () => ({ increment: () => ++mockedIncrement }));
});

test('Importieren des nächsten Moduls importiert das gemockte', async () => {
  // der ursprüngliche Import WURDE NICHT GEMOCKT, da vi.doMock NACH den Importen ausgewertet wird
  expect(increment(1)).toBe(2);
  const { increment: mockedIncrement } = await import('./increment.js');
  // der neue dynamische Import gibt gemocktes Modul zurück
  expect(mockedIncrement(1)).toBe(101);
  expect(mockedIncrement(1)).toBe(102);
  expect(mockedIncrement(1)).toBe(103);
});

vi.mocked ​

  • Typ: <T>(obj: T, deep?: boolean) => MaybeMockedDeep<T>
  • Typ: <T>(obj: T, options?: { partial?: boolean; deep?: boolean }) => MaybePartiallyMockedDeep<T>

Typ-Helfer für TypeScript. Gibt einfach das übergebene Objekt zurück.

Wenn partial true ist, wird ein Partial<T> als Rückgabewert erwartet. Standardmäßig geht TypeScript nur davon aus, dass die Werte der ersten Ebene gemockt sind. Sie können { deep: true } als zweites Argument übergeben, um TypeScript mitzuteilen, dass das gesamte Objekt gemockt ist, sofern dies zutrifft.

ts
export function add(x: number, y: number): number {
  return x + y;
}

export function fetchSomething(): Promise<Response> {
  return fetch('https://vitest.dev/');
}
ts
import * as example from './example';

vi.mock('./example');

test('1 + 1 ist gleich 10', async () => {
  vi.mocked(example.add).mockReturnValue(10);
  expect(example.add(1, 1)).toBe(10);
});

test('Mock-Rückgabewert mit nur teilweise korrekter Typisierung', async () => {
  vi.mocked(example.fetchSomething).mockResolvedValue(new Response('hello'));
  vi.mocked(example.fetchSomething, { partial: true }).mockResolvedValue({
    ok: false,
  });
  // vi.mocked(example.someFn).mockResolvedValue({ ok: false }) // dies ist ein Typfehler
});

vi.importActual ​

  • Typ: <T>(path: string) => Promise<T>

Importiert ein Modul und umgeht dabei alle Prüfungen, ob es gemockt werden muss. Dies kann nützlich sein, wenn Sie ein Modul teilweise mocken möchten.

ts
vi.mock('./example.js', async () => {
  const originalModule = await vi.importActual('./example.js');

  return { ...originalModule, get: vi.fn() };
});

vi.importMock ​

  • Typ: <T>(path: string) => Promise<MaybeMockedDeep<T>>

Importiert ein Modul, bei dem alle seine Eigenschaften (einschließlich verschachtelter Eigenschaften) gemockt sind. Folgt denselben Regeln wie vi.mock. Die angewendeten Regeln finden Sie unter Algorithmus.

vi.unmock ​

  • Typ: (path: string | Promise<Module>) => void

Entfernt das Modul aus dem Mock-Register. Alle Aufrufe zum Importieren geben das ursprüngliche Modul zurück, auch wenn es zuvor gemockt wurde. Dieser Aufruf wird an den Anfang der Datei hochgezogen, sodass dadurch nur Module entmockt werden, die beispielsweise in setupFiles definiert wurden.

vi.doUnmock ​

  • Typ: (path: string | Promise<Module>) => void

Dasselbe wie vi.unmock, wird aber nicht an den Anfang der Datei hochgezogen. Beim nächsten Import des Moduls wird das ursprüngliche Modul anstelle des Mocks importiert. Diese Methode wird zuvor importierte Module nicht entmocken.

ts
export function increment(number) {
  return number + 1;
}
ts
import { increment } from './increment.js';

// increment ist bereits gemockt, da vi.mock hochgezogen wurde
increment(1) === 100;

// dieser vi.mock-Aufruf wird hochgezogen, und die Factory wird vor dem Import in Zeile 1 aufgerufen
vi.mock('./increment.js', () => ({ increment: () => 100 }));

// alle Aufrufe der Funktion sind gemockt, und `increment` gibt immer 100 zurück
increment(1) === 100;
increment(30) === 100;

// dies wird nicht hochgezogen, daher gibt ein anderer Import ein ungemocktes Modul zurück
vi.doUnmock('./increment.js');

// der Aufruf von increment gibt IMMER NOCH 100 zurück, da vi.doUnmock ein Modul nicht neu auswertet
increment(1) === 100;
increment(30) === 100;

// durch den nächsten Import ist das Modul ungemockt, jetzt ist `increment` die ursprüngliche Funktion, die count + 1 zurückgibt
const { increment: unmockedIncrement } = await import('./increment.js');

unmockedIncrement(1) === 2;
unmockedIncrement(30) === 31;

vi.resetModules ​

  • Typ: () => Vitest

Setzt das Modulregister zurück, indem der Cache aller Module geleert wird. Dadurch können Module bei erneutem Import neu bewertet werden. Importe auf oberster Ebene können nicht neu bewertet werden. Dies kann nützlich sein, um Module zu isolieren, bei denen lokale Zustände zwischen Tests kollidieren.

ts
import { vi } from 'vitest';

import { data } from './data.js'; // Wird nicht vor jedem Test neu bewertet

beforeEach(() => {
  vi.resetModules();
});

test('Zustand ändern', async () => {
  const mod = await import('./some/path.js'); // Wird erneut ausgewertet
  mod.changeLocalState('neuer Wert');
  expect(mod.getLocalState()).toBe('neuer Wert');
});

test('Modul hat alten Zustand', async () => {
  const mod = await import('./some/path.js'); // Wird erneut ausgewertet
  expect(mod.getLocalState()).toBe('alter Wert');
});

WARNING

Setzt das Mock-Register nicht zurück. Um das Mock-Register zu leeren, verwenden Sie vi.unmock oder vi.doUnmock.

vi.dynamicImportSettled ​

Wartet, bis alle dynamischen Importe geladen sind. Nützlich, wenn Sie einen synchronen Aufruf haben, der den Import eines Moduls startet, auf das Sie sonst nicht warten können.

ts
import { expect, test } from 'vitest';

// Import kann nicht verfolgt werden, da kein Promise zurückgegeben wird
function renderComponent() {
  import('./component.js').then(({ render }) => {
    render();
  });
}

test('Operationen sind aufgelöst', async () => {
  renderComponent();
  await vi.dynamicImportSettled();
  expect(document.querySelector('.component')).not.toBeNull();
});

TIP

Wenn während eines dynamischen Imports ein weiterer dynamischer Import initiiert wird, wartet diese Methode, bis alle Importe aufgelöst sind.

Diese Methode wartet auch auf den nächsten setTimeout-Tick, nachdem der Import aufgelöst wurde, sodass alle synchronen Operationen abgeschlossen sein sollten, sobald der Import aufgelöst ist.

Funktionen und Objekte mocken ​

Dieser Abschnitt beschreibt, wie man mit Methoden-Mocks arbeitet und Umgebungs- und globale Variablen ersetzt.

vi.fn ​

  • Typ: (fn?: Function) => Mock

Erstellt einen Spy auf eine Funktion, kann aber auch ohne eine solche initialisiert werden. Jedes Mal, wenn eine Funktion aufgerufen wird, speichert sie ihre Aufrufargumente, Rückgabewerte und Instanzen. Außerdem können Sie das Verhalten des Spys mit Methoden manipulieren. Wenn keine Funktion angegeben wird, gibt der Mock undefined zurück, sobald er aufgerufen wird.

ts
const getApples = vi.fn(() => 0);

getApples();

expect(getApples).toHaveBeenCalled();
expect(getApples).toHaveReturnedWith(0);

getApples.mockReturnValueOnce(5);

const res = getApples();
expect(res).toBe(5);
expect(getApples).toHaveNthReturnedWith(2, 5);

vi.mockObject 3.2.0+ ​

  • Typ: <T>(value: T) => MaybeMockedDeep<T>

Mockt Eigenschaften und Methoden eines gegebenen Objekts rekursiv auf die gleiche Weise, wie vi.mock() Modulexporte mockt. Details finden Sie unter Automocking.

ts
const original = {
  simple: () => 'value',
  nested: {
    method: () => 'real',
  },
  prop: 'foo',
};

const mocked = vi.mockObject(original);
expect(mocked.simple()).toBe(undefined);
expect(mocked.nested.method()).toBe(undefined);
expect(mocked.prop).toBe('foo');

mocked.simple.mockReturnValue('mocked');
mocked.nested.method.mockReturnValue('mocked nested');

expect(mocked.simple()).toBe('mocked');
expect(mocked.nested.method()).toBe('mocked nested');

vi.isMockFunction ​

  • Typ: (fn: Function) => boolean

Prüft, ob der übergebene Parameter eine Mock-Funktion ist. Wenn Sie TypeScript verwenden, wird dadurch auch der Typ eingegrenzt.

vi.clearAllMocks ​

Ruft .mockClear() für alle Spies auf. Diese Methode löscht den Mock-Verlauf, ohne die Mock-Implementierungen zu beeinflussen.

vi.resetAllMocks ​

Ruft .mockReset() für alle Spies auf. Dies löscht den Mock-Verlauf und setzt die Implementierung jedes Mocks auf ihre ursprüngliche zurück.

vi.restoreAllMocks ​

Ruft .mockRestore() für alle Spies auf. Diese Methode löscht den Mock-Verlauf, stellt alle ursprünglichen Mock-Implementierungen wieder her und stellt die ursprünglichen Deskriptoren der gespionten Objekte wieder her.

vi.spyOn ​

  • Typ: <T, K extends keyof T>(object: T, method: K, accessType?: 'get' | 'set') => MockInstance

Erstellt einen Spy auf eine Methode oder einen Getter/Setter eines Objekts, ähnlich wie vi.fn(). Diese Methode gibt eine Mock-Funktion zurück.

ts
let apples = 0;
const cart = {
  getApples: () => 42,
};

const spy = vi.spyOn(cart, 'getApples').mockImplementation(() => apples);
apples = 1;

expect(cart.getApples()).toBe(1);

expect(spy).toHaveBeenCalled();
expect(spy).toHaveReturnedWith(1);

TIP

In Umgebungen, die Explizites Ressourcenmanagement unterstützen, können Sie using anstelle von const verwenden, um mockRestore automatisch für jede gemockte Funktion aufzurufen, wenn der enthaltende Block verlassen wird. Dies erweist sich als besonders nützlich für gespionte Methoden:

ts
it('ruft console.log auf', () => {
  using spy = vi.spyOn(console, 'log').mockImplementation(() => {})
  debug('Nachricht')
  expect(spy).toHaveBeenCalled()
})
// console.log wird hier wiederhergestellt

TIP

Sie können vi.restoreAllMocks innerhalb von afterEach aufrufen oder test.restoreMocks aktivieren, um alle Methoden auf ihre ursprünglichen Implementierungen zurückzusetzen. Dadurch wird der ursprüngliche Objekt-Deskriptor wiederhergestellt, sodass Sie die Implementierung der Methode nicht ändern können:

ts
const cart = {
  getApples: () => 42,
};

const spy = vi.spyOn(cart, 'getApples').mockReturnValue(10);

console.log(cart.getApples()); // 10
vi.restoreAllMocks();
console.log(cart.getApples()); // 42
spy.mockReturnValue(10);
console.log(cart.getApples()); // immer noch 42!

TIP

Es ist nicht möglich, exportierte Methoden im Browser-Modus auszuspionieren. Stattdessen können Sie jede exportierte Methode ausspionieren, indem Sie vi.mock("./file-path.js", { spy: true }) aufrufen. Dieser Aufruf mockt jeden Export, behält aber seine Implementierung intakt, sodass Sie überprüfen können, ob die Methode korrekt aufgerufen wurde.

ts
import { calculator } from './src/calculator.ts';

vi.mock('./src/calculator.ts', { spy: true });

calculator(1, 2);

expect(calculator).toHaveBeenCalledWith(1, 2);
expect(calculator).toHaveReturned(3);

Und obwohl es möglich ist, Exporte in jsdom oder anderen Node.js-Umgebungen auszuspionieren, könnte sich dies in Zukunft ändern.

vi.stubEnv ​

  • Typ: <T extends string>(name: T, value: T extends "PROD" | "DEV" | "SSR" ? boolean : string | undefined) => Vitest

Ändert den Wert von Umgebungsvariablen in process.env und import.meta.env. Sie können ihren Wert durch Aufruf von vi.unstubAllEnvs wiederherstellen.

ts
import { vi } from 'vitest';

// `process.env.NODE_ENV` und `import.meta.env.NODE_ENV`
// sind "development" bevor "vi.stubEnv" aufgerufen wird

vi.stubEnv('NODE_ENV', 'production');

process.env.NODE_ENV === 'production';
import.meta.env.NODE_ENV === 'production';

vi.stubEnv('NODE_ENV', undefined);

process.env.NODE_ENV === undefined;
import.meta.env.NODE_ENV === undefined;

// ändert andere Umgebungen nicht
import.meta.env.MODE === 'development';

TIP

Sie können den Wert auch einfach durch direkte Zuweisung ändern, aber Sie können vi.unstubAllEnvs nicht verwenden, um den vorherigen Wert wiederherzustellen:

ts
import.meta.env.MODE = 'test';

vi.unstubAllEnvs ​

  • Typ: () => Vitest

Stellt alle import.meta.env- und process.env-Werte wieder her, die mit vi.stubEnv geändert wurden. Wenn diese Methode zum ersten Mal aufgerufen wird, merkt sich Vitest den ursprünglichen Wert und speichert ihn, bis unstubAllEnvs erneut aufgerufen wird.

ts
import { vi } from 'vitest';

// `process.env.NODE_ENV` und `import.meta.env.NODE_ENV`
// sind "development" vor dem Aufruf von stubEnv

vi.stubEnv('NODE_ENV', 'production');

process.env.NODE_ENV === 'production';
import.meta.env.NODE_ENV === 'production';

vi.stubEnv('NODE_ENV', 'staging');

process.env.NODE_ENV === 'staging';
import.meta.env.NODE_ENV === 'staging';

vi.unstubAllEnvs();

// stellt den Wert wieder her, der vor dem ersten "stubEnv"-Aufruf gespeichert war
process.env.NODE_ENV === 'development';
import.meta.env.NODE_ENV === 'development';

vi.stubGlobal ​

  • Typ: (name: string | number | symbol, value: unknown) => Vitest

Ändert den Wert von globalen Variablen. Sie können den ursprünglichen Wert durch Aufruf von vi.unstubAllGlobals wiederherstellen.

ts
import { vi } from 'vitest';

// `innerWidth` ist "0" vor dem Aufruf von stubGlobal

vi.stubGlobal('innerWidth', 100);

innerWidth === 100;
globalThis.innerWidth === 100;
// wenn Sie jsdom oder happy-dom verwenden
window.innerWidth === 100;

TIP

Sie können den Wert auch einfach durch direkte Zuweisung an globalThis oder window (wenn Sie die jsdom- oder happy-dom-Umgebung verwenden) ändern, aber Sie können vi.unstubAllGlobals nicht verwenden, um den ursprünglichen Wert wiederherzustellen:

ts
globalThis.innerWidth = 100;
// wenn Sie jsdom oder happy-dom verwenden
window.innerWidth = 100;

vi.unstubAllGlobals ​

  • Typ: () => Vitest

Stellt alle globalen Werte auf globalThis/global (und window/top/self/parent, wenn Sie die jsdom- oder happy-dom-Umgebung verwenden) wieder her, die mit vi.stubGlobal geändert wurden. Wenn diese Methode zum ersten Mal aufgerufen wird, merkt sich Vitest den ursprünglichen Wert und speichert ihn, bis unstubAllGlobals erneut aufgerufen wird.

ts
import { vi } from 'vitest';

const Mock = vi.fn();

// IntersectionObserver ist "undefined" vor dem Aufruf von "stubGlobal"

vi.stubGlobal('IntersectionObserver', Mock);

IntersectionObserver === Mock;
global.IntersectionObserver === Mock;
globalThis.IntersectionObserver === Mock;
// wenn Sie jsdom oder happy-dom verwenden
window.IntersectionObserver === Mock;

vi.unstubAllGlobals();

globalThis.IntersectionObserver === undefined;
'IntersectionObserver' in globalThis === false;
// wirft ReferenceError, da dies nicht definiert ist
IntersectionObserver === undefined;

Fake-Timer ​

Dieser Abschnitt beschreibt, wie man mit Fake-Timern arbeitet.

vi.advanceTimersByTime ​

  • Typ: (ms: number) => Vitest

Diese Methode ruft jeden gestarteten Timer auf, bis die angegebene Anzahl von Millisekunden verstrichen ist oder die Warteschlange leer ist – je nachdem, was zuerst eintritt.

ts
let i = 0;
setInterval(() => console.log(++i), 50);

vi.advanceTimersByTime(150);

// log: 1
// log: 2
// log: 3

vi.advanceTimersByTimeAsync ​

  • Typ: (ms: number) => Promise<Vitest>

Diese Methode ruft jeden gestarteten Timer auf, bis die angegebene Anzahl von Millisekunden verstrichen ist oder die Warteschlange leer ist – je nachdem, was zuerst eintritt. Dabei werden auch asynchron gesetzte Timer eingeschlossen.

ts
let i = 0;
setInterval(() => Promise.resolve().then(() => console.log(++i)), 50);

await vi.advanceTimersByTimeAsync(150);

// log: 1
// log: 2
// log: 3

vi.advanceTimersToNextTimer ​

  • Typ: () => Vitest

Diese Methode ruft den nächsten verfügbaren Timer auf. Nützlich, um Zusicherungen zwischen jedem Timer-Aufruf durchzuführen. Sie können diese Methode verketten, um Timer selbst zu verwalten.

ts
let i = 0;
setInterval(() => console.log(++i), 50);

vi.advanceTimersToNextTimer() // log: 1
  .advanceTimersToNextTimer() // log: 2
  .advanceTimersToNextTimer(); // log: 3

vi.advanceTimersToNextTimerAsync ​

  • Typ: () => Promise<Vitest>

Ruft den nächsten verfügbaren Timer auf und wartet, bis dieser aufgelöst ist, falls er asynchron gesetzt wurde. Nützlich, um Zusicherungen zwischen jedem Timer-Aufruf zu machen.

ts
let i = 0;
setInterval(() => Promise.resolve().then(() => console.log(++i)), 50);

await vi.advanceTimersToNextTimerAsync(); // log: 1
expect(console.log).toHaveBeenCalledWith(1);

await vi.advanceTimersToNextTimerAsync(); // log: 2
await vi.advanceTimersToNextTimerAsync(); // log: 3

vi.advanceTimersToNextFrame 2.1.0+ ​

  • Typ: () => Vitest

Ähnlich wie vi.advanceTimersByTime, aber diese Methode wird die Timer um die Millisekunden vorrücken, die benötigt werden, um Rückrufe auszuführen, die derzeit mit requestAnimationFrame geplant sind.

ts
let frameRendered = false;

requestAnimationFrame(() => {
  frameRendered = true;
});

vi.advanceTimersToNextFrame();

expect(frameRendered).toBe(true);

vi.getTimerCount ​

  • Typ: () => number

Gibt die Anzahl der wartenden Timer zurück.

vi.clearAllTimers ​

Diese Methode entfernt alle Timer, die zur Ausführung geplant sind. Diese Timer werden in Zukunft nicht mehr ausgeführt.

vi.getMockedSystemTime ​

  • Typ: () => Date | null

Gibt das gemockte aktuelle Datum zurück. Wenn das Datum nicht gemockt ist, gibt die Methode null zurück.

vi.getRealSystemTime ​

  • Typ: () => number

Bei Verwendung von vi.useFakeTimers werden Aufrufe von Date.now gemockt. Wenn Sie die reale Zeit in Millisekunden erhalten müssen, können Sie diese Funktion aufrufen.

vi.runAllTicks ​

  • Typ: () => Vitest

Diese Methode ruft jede Mikroaufgabe auf, die von process.nextTick in die Warteschlange gestellt wurde. Dabei werden auch alle Mikroaufgaben ausgeführt, die von sich selbst geplant wurden.

vi.runAllTimers ​

  • Typ: () => Vitest

Diese Methode ruft jeden gestarteten Timer auf, bis die Timer-Warteschlange leer ist. Das bedeutet, dass jeder Timer, der während runAllTimers aufgerufen wird, getriggert wird. Wenn Sie ein unendliches Intervall haben, wird ein Fehler nach 10.000 Versuchen ausgelöst (kann mit fakeTimers.loopLimit konfiguriert werden).

ts
let i = 0;
setTimeout(() => console.log(++i));
const interval = setInterval(() => {
  console.log(++i);
  if (i === 3) {
    clearInterval(interval);
  }
}, 50);

vi.runAllTimers();

// log: 1
// log: 2
// log: 3

vi.runAllTimersAsync ​

  • Typ: () => Promise<Vitest>

Diese Methode ruft jeden gestarteten Timer asynchron auf, bis die Timer-Warteschlange leer ist. Das bedeutet, dass jeder Timer, der während runAllTimersAsync aufgerufen wird, getriggert wird, einschließlich asynchroner Timer. Wenn Sie ein unendliches Intervall haben, wird nach 10.000 Versuchen ein Fehler ausgelöst (kann mit fakeTimers.loopLimit konfiguriert werden).

ts
setTimeout(async () => {
  console.log(await Promise.resolve('Ergebnis'));
}, 100);

await vi.runAllTimersAsync();

// log: Ergebnis

vi.runOnlyPendingTimers ​

  • Typ: () => Vitest

Diese Methode ruft jeden Timer auf, der nach dem Aufruf von vi.useFakeTimers gestartet wurde. Sie löst keine Timer aus, die während ihres Aufrufs initiiert wurden.

ts
let i = 0;
setInterval(() => console.log(++i), 50);

vi.runOnlyPendingTimers();

// log: 1

vi.runOnlyPendingTimersAsync ​

  • Typ: () => Promise<Vitest>

Diese Methode ruft jeden Timer, der nach dem Aufruf von vi.useFakeTimers gestartet wurde, asynchron auf, einschließlich asynchroner Timer. Dabei werden keine Timer ausgelöst, die während ihres Aufrufs initiiert wurden.

ts
setTimeout(() => {
  console.log(1);
}, 100);
setTimeout(() => {
  Promise.resolve().then(() => {
    console.log(2);
    setInterval(() => {
      console.log(3);
    }, 40);
  });
}, 10);

await vi.runOnlyPendingTimersAsync();

// log: 2
// log: 3
// log: 3
// log: 1

vi.setSystemTime ​

  • Typ: (date: string | number | Date) => void

Wenn Fake-Timer aktiviert sind, simuliert diese Methode eine Änderung der Systemuhr durch den Benutzer (wirkt sich auf datumsbezogene APIs wie hrtime, performance.now oder new Date() aus) – sie löst jedoch keine Timer aus. Wenn Fake-Timer nicht aktiviert sind, mockt diese Methode nur Aufrufe von Date.*.

Nützlich, wenn Sie etwas testen müssen, das vom aktuellen Datum abhängt – zum Beispiel Aufrufe von Luxon in Ihrem Code.

Akzeptiert dieselben String- und Zahlenargumente wie der Date-Konstruktor.

ts
const date = new Date(1998, 11, 19);

vi.useFakeTimers();
vi.setSystemTime(date);

expect(Date.now()).toBe(date.valueOf());

vi.useRealTimers();

vi.useFakeTimers ​

  • Typ: (config?: FakeTimerInstallOpts) => Vitest

Um das Mocking von Timern zu aktivieren, müssen Sie diese Methode aufrufen. Sie umschließt alle weiteren Aufrufe von Timern (wie setTimeout, setInterval, clearTimeout, clearInterval, setImmediate, clearImmediate und Date), bis vi.useRealTimers() aufgerufen wird.

Das Mocken von nextTick wird nicht unterstützt, wenn Vitest innerhalb von node:child_process mit --pool=forks ausgeführt wird. NodeJS verwendet process.nextTick intern in node:child_process und blockiert, wenn es gemockt wird. Das Mocken von nextTick wird unterstützt, wenn Vitest mit --pool=threads ausgeführt wird.

Die Implementierung basiert intern auf @sinonjs/fake-timers.

TIP

vi.useFakeTimers() mockt process.nextTick und queueMicrotask nicht automatisch. Sie können dies jedoch aktivieren, indem Sie die Option im toFake-Argument angeben: vi.useFakeTimers({ toFake: ['nextTick', 'queueMicrotask'] }).

vi.isFakeTimers ​

  • Typ: () => boolean

Gibt true zurück, wenn Fake-Timer aktiviert sind.

vi.useRealTimers ​

  • Typ: () => Vitest

Wenn die Timer abgelaufen sind, können Sie diese Methode aufrufen, um gemockte Timer auf ihre ursprünglichen Implementierungen zurückzusetzen. Alle zuvor geplanten Timer werden dabei verworfen.

Verschiedenes ​

Eine Reihe nützlicher Hilfsfunktionen, die Vitest bereitstellt.

vi.waitFor ​

  • Typ: <T>(callback: WaitForCallback<T>, options?: number | WaitForOptions) => Promise<T>

Wartet, bis der Callback erfolgreich ausgeführt wurde. Wenn der Callback einen Fehler auslöst oder ein abgelehnter Promise zurückgegeben wird, wartet die Methode weiter, bis der Callback erfolgreich ist oder ein Timeout eintritt.

Wenn options auf eine Zahl gesetzt ist, entspricht dies dem Setzen von { timeout: options }.

Dies erweist sich als sehr nützlich, wenn Sie auf den Abschluss einer asynchronen Aktion warten müssen, z. B. wenn Sie einen Server starten und warten müssen, bis er gestartet ist.

ts
import { expect, test, vi } from 'vitest';
import { createServer } from './server.js';

test('Server erfolgreich gestartet wurde', async () => {
  const server = createServer();

  await vi.waitFor(
    () => {
      if (!server.isReady) {
        throw new Error('Server ist nicht gestartet');
      }

      console.log('Server gestartet');
    },
    {
      timeout: 500, // Standard ist 1000
      interval: 20, // Standard ist 50
    }
  );
  expect(server.isReady).toBe(true);
});

Es funktioniert auch für asynchrone Callbacks

ts
// @vitest-environment jsdom

import { expect, test, vi } from 'vitest';
import { getDOMElementAsync, populateDOMAsync } from './dom.js';

test('Element existiert im DOM', async () => {
  // Beginne mit der DOM-Befüllung
  populateDOMAsync();

  const element = await vi.waitFor(
    async () => {
      // versuchen, das Element zu finden, bis es existiert
      const element = (await getDOMElementAsync()) as HTMLElement | null;
      expect(element).toBeTruthy();
      expect(element.dataset.initialized).toBeTruthy();
      return element;
    },
    {
      timeout: 500, // Standard ist 1000
      interval: 20, // Standard ist 50
    }
  );
  expect(element).toBeInstanceOf(HTMLElement);
});

Wenn vi.useFakeTimers verwendet wird, ruft vi.waitFor automatisch vi.advanceTimersByTime(interval) bei jedem Check-Callback auf.

vi.waitUntil ​

  • Typ: <T>(callback: WaitUntilCallback<T>, options?: number | WaitUntilOptions) => Promise<T>

Dies ähnelt vi.waitFor, aber wenn der Callback Fehler auslöst, wird die Ausführung sofort unterbrochen und eine Fehlermeldung empfangen. Wenn der Callback einen Falsy-Wert zurückgibt, wird die nächste Prüfung fortgesetzt, bis ein Truthy-Wert zurückgegeben wird. Dies erweist sich als nützlich, wenn Sie warten müssen, bis etwas existiert, bevor Sie den nächsten Schritt unternehmen.

Betrachten Sie das folgende Beispiel. Wir können vi.waitUntil verwenden, um zu warten, bis das Element auf der Seite erscheint, und dann können wir etwas mit dem Element tun.

ts
import { expect, test, vi } from 'vitest';

test('Element wird korrekt gerendert', async () => {
  const element = await vi.waitUntil(() => document.querySelector('.element'), {
    timeout: 500, // Standard ist 1000
    interval: 20, // Standard ist 50
  });

  // etwas mit dem Element tun
  expect(element.querySelector('.element-child')).toBeTruthy();
});

vi.hoisted ​

  • Typ: <T>(factory: () => T) => T

Alle statischen import-Anweisungen in ES-Modulen werden an den Anfang der Datei hochgezogen, sodass jeder Code, der vor den Importen definiert ist, tatsächlich nach der Auswertung der Importe ausgeführt wird.

Es kann jedoch nützlich sein, einige Nebeneffekte wie das Mocken von Daten vor dem Importieren eines Moduls auszulösen.

Um diese Einschränkung zu umgehen, können Sie statische Importe wie folgt in dynamische umschreiben:

diff
callFunctionWithSideEffect()
- import { value } from './some/module.js'
+ const { value } = await import('./some/module.js')

Beim Ausführen von Vitest können Sie dies automatisch mit der Methode vi.hoisted erreichen. Intern konvertiert Vitest statische Importe in dynamische mit beibehaltenen Live-Bindungen.

diff
- callFunctionWithSideEffect()
import { value } from './some/module.js'
+ vi.hoisted(() => callFunctionWithSideEffect())

IMPORTE SIND NICHT VERFÜGBAR

Codeausführung vor den Importen bedeutet, dass Sie nicht auf importierte Variablen zugreifen können, da diese noch nicht definiert sind:

ts
import { value } from './some/module.js';

vi.hoisted(() => { value }); // wirft einen Fehler

Dieser Code erzeugt einen Fehler:

Kann nicht auf '__vi_import_0__' vor der Initialisierung zugreifen

Wenn Sie auf eine Variable aus einem anderen Modul innerhalb von vi.hoisted zugreifen müssen, verwenden Sie den dynamischen Import:

ts
await vi.hoisted(async () => {
  const { value } = await import('./some/module.js');
});

Es wird jedoch abgeraten, etwas innerhalb von vi.hoisted zu importieren, da Importe bereits hochgezogen sind – wenn Sie etwas ausführen müssen, bevor die Tests laufen, führen Sie es einfach im importierten Modul selbst aus.

Diese Methode gibt den Wert zurück, der von der Factory zurückgegeben wurde. Sie können diesen Wert in Ihren vi.mock-Factories verwenden, wenn Sie einfachen Zugriff auf lokal definierte Variablen benötigen:

ts
import { expect, vi } from 'vitest';
import { originalMethod } from './path/to/module.js';

const { mockedMethod } = vi.hoisted(() => {
  return { mockedMethod: vi.fn() };
});

vi.mock('./path/to/module.js', () => {
  return { originalMethod: mockedMethod };
});

mockedMethod.mockReturnValue(100);
expect(originalMethod()).toBe(100);

Beachten Sie, dass diese Methode auch asynchron aufgerufen werden kann, selbst wenn Ihre Umgebung kein Top-Level-Await unterstützt:

ts
const json = await vi.hoisted(async () => {
  const response = await fetch('https://jsonplaceholder.typicode.com/posts');
  return response.json();
});

vi.setConfig ​

  • Typ: RuntimeConfig

Aktualisiert die Konfiguration für die aktuelle Testdatei. Diese Methode unterstützt nur Konfigurationsoptionen, die sich auf die aktuelle Testdatei auswirken:

ts
vi.setConfig({
  allowOnly: true,
  testTimeout: 10_000,
  hookTimeout: 10_000,
  clearMocks: true,
  restoreMocks: true,
  fakeTimers: {
    now: new Date(2021, 11, 19),
    // unterstützt das gesamte Objekt
  },
  maxConcurrency: 10,
  sequence: {
    hooks: 'stack',
    // unterstützt nur "sequence.hooks"
  },
});

vi.resetConfig ​

  • Typ: RuntimeConfig

Wenn vi.setConfig zuvor aufgerufen wurde, setzt diese Methode die Konfiguration auf den ursprünglichen Zustand zurück.

Pager
Vorherige SeiteMock-Funktionen
Nächste Seiteexpect

Veröffentlicht unter der MIT-Lizenz.

Copyright (c) 2021-Present Vitest Team

https://vitest.dev/api/vi

Veröffentlicht unter der MIT-Lizenz.

Copyright (c) 2021-Present Vitest Team