Skip to content
Vitest 2
Main Navigation LeitfadenAPIKonfigurationBrowser-ModusFortgeschritten
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

Test API Referenz

Mock-Funktionen

Vi

expect

expectTypeOf

assert

assertType

Auf dieser Seite

Vi ​

Vitest stellt Hilfsfunktionen über seinen vi-Helfer bereit. Sie können global darauf zugreifen (wenn die globale Konfiguration aktiviert ist) oder es direkt aus vitest importieren:

js
import { vi } from 'vitest';

Module mocken ​

Dieser Abschnitt beschreibt die API, die Sie beim Mocken eines Moduls verwenden können. 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 des Moduls vom angegebenen path durch ein anderes Modul. Sie können konfigurierte Vite-Aliase innerhalb eines Pfades verwenden. Der Aufruf von vi.mock wird an den Anfang der Datei verschoben (hoisted), sodass es keine Rolle spielt, wo Sie ihn aufrufen. Er wird immer vor allen Importanweisungen ausgeführt. Wenn Sie auf Variablen außerhalb seines Geltungsbereichs zugreifen müssen, 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 an den Anfang der Datei zu verschieben, analysiert Vitest Ihre Dateien statisch. Das bedeutet, dass vi nicht verwendet werden kann, wenn es nicht direkt aus dem vitest-Paket importiert wurde (z. B. aus einer Hilfsdatei). Verwenden Sie vi.mock mit vi, das aus vitest importiert wurde, oder aktivieren Sie die Konfigurationsoption globals.

Vitest mockt keine Module, die in einer Setup-Datei importiert wurden, da diese bereits zwischengespeichert sind, wenn eine Testdatei ausgeführt wird. Sie können vi.resetModules() innerhalb von vi.hoisted aufrufen, um alle Modul-Caches zu löschen, bevor eine Testdatei ausgeführt wird.

Wenn die factory-Funktion definiert ist, geben alle Importe ihr Ergebnis zurück. Vitest ruft die Factory nur einmal auf und verwendet das Ergebnis für alle nachfolgenden Importe, 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, dem die Factory als erstes Argument übergeben wird, um das ursprüngliche Modul darin zu erhalten.

Seit Vitest 2.1 können Sie anstelle einer Factory-Funktion auch ein Objekt mit einer spy-Eigenschaft bereitstellen. Wenn spy auf true gesetzt ist, mockt Vitest das Modul wie gewohnt automatisch, behält aber die ursprüngliche Implementierung der Exporte bei. Dies ist nützlich, wenn Sie nur überprüfen möchten, ob eine exportierte Methode von einer anderen Methode korrekt 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, das ein Modul auflöst, 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, und der Typ von importOriginal wird automatisch abgeleitet. Die Verwendung dieser Signatur stellt auch sicher, dass der Rückgabetyp der Factory mit dem ursprünglichen Modul kompatibel ist (wobei Exporte optional sein können).

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 weiterhin mit einem String und nicht mit einem Modulobjekt.

Wenn Sie jedoch TypeScript mit in tsconfig.json konfigurierten paths-Aliasen verwenden, kann der Compiler die Importtypen möglicherweise nicht korrekt auflösen. Damit dies funktioniert, stellen Sie sicher, dass Sie alle Importe mit Aliasen durch ihre entsprechenden relativen Pfade ersetzen. Verwenden Sie z. B. import('./path/to/module.js') anstelle von import('@/module').

WARNING

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

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

Wenn Sie Variablen innerhalb der Factory verwenden müssen, versuchen Sie vi.doMock. Es funktioniert auf die gleiche Weise, wird aber nicht an den Anfang der Datei verschoben. Beachten Sie, dass es nur nachfolgende Importe beeinflusst.

Sie können auch auf Variablen verweisen, die durch die Methode vi.hoisted definiert wurden, sofern diese 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üssen Sie einen default-Schlüssel innerhalb des zurückgegebenen Factory-Funktionsobjekts bereitstellen. Dies ist eine Besonderheit von ES-Modulen; 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 neben einer Datei, die Sie mocken, ein __mocks__-Ordner befindet 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.

Zum Beispiel haben Sie diese Dateistruktur:

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

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

ts
// increment.test.js
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 Sie vi.mock nicht aufrufen. Um das Automocking-Verhalten von Jest zu replizieren, können Sie vi.mock für jedes benötigte Modul innerhalb von setupFiles aufrufen.

Wenn kein __mocks__-Ordner oder keine Factory bereitgestellt wird, importiert Vitest das ursprüngliche Modul und mockt automatisch 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, wird aber nicht an den Anfang der Datei verschoben, sodass Sie auf Variablen im globalen Dateibereich verweisen können. Der nächste dynamische Import des Moduls wird durch einen Mock ersetzt.

WARNING

Dies beeinflusst keine Module, die vor diesem Aufruf importiert wurden. Vergessen Sie nicht, dass alle statischen Importe in ESM immer an den Anfang der Datei verschoben werden, sodass das Platzieren dieses vor einem statischen Import nicht dazu führt, dass es vor dem Import aufgerufen wird:

ts
vi.doMock('./increment.js'); // dies wird **nach** der Importanweisung aufgerufen

import { increment } from './increment.js';
ts
// ./increment.js
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('importing the next module imports mocked one', 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');
  // neuer dynamischer 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>

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

Wenn partial auf true gesetzt ist, erwartet es einen Partial<T> als Rückgabewert. Standardmäßig lässt dies TypeScript nur annehmen, 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, falls dies zutrifft.

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

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

vi.mock('./example');

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

test('mock return value with only partially correct typing', 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 führt zu einem Typfehler
});

vi.importActual ​

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

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

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

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

vi.importMock ​

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

Importiert ein Modul, bei dem alle Eigenschaften (einschließlich verschachtelter Eigenschaften) gemockt sind. Es 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 Importaufrufe geben das ursprüngliche Modul zurück, selbst wenn es zuvor gemockt wurde. Dieser Aufruf wird an den Anfang der Datei verschoben, sodass er nur Module entmockt, 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 verschoben. Beim nächsten Import des Moduls wird das ursprüngliche Modul anstelle des Mocks importiert. Dies beeinflusst keine zuvor importierten Module.

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

// increment ist bereits gemockt, da `vi.mock` an den Anfang der Datei verschoben wurde
increment(1) === 100;

// dies wird an den Anfang der Datei verschoben, und die Factory wird vor dem Import in Zeile 1 aufgerufen
vi.mock('./increment.js', () => ({ increment: () => 100 }));

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

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

// dies gibt **immer noch** 100 zurück, da `vi.doUnmock` ein Modul nicht neu auswertet
increment(1) === 100;
increment(30) === 100;

// der nächste Import ist 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 gelöscht wird. Dadurch können Module beim erneuten Import neu ausgewertet werden. Top-Level-Importe können nicht neu ausgewertet werden. Kann nützlich sein, um Module zu isolieren, bei denen lokale Zustände zwischen Tests in Konflikt geraten.

ts
import { vi } from 'vitest';

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

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

test('change state', async () => {
  const mod = await import('./some/path.js'); // Wird neu ausgewertet
  mod.changeLocalState('new value');
  expect(mod.getLocalState()).toBe('new value');
});

test('module has old state', async () => {
  const mod = await import('./some/path.js'); // Wird neu ausgewertet
  expect(mod.getLocalState()).toBe('old value');
});

WARNING

Setzt das Mock-Register nicht zurück. Um das Mock-Register zu löschen, 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';

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

test('operations are resolved', 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 aufgelöst sind.

Diese Methode wartet auch auf den nächsten setTimeout-Tick, nachdem der Import aufgelöst wurde. Dadurch sollten alle synchronen Operationen abgeschlossen sein, wenn er aufgelöst wird.

Funktionen und Objekte mocken ​

Dieser Abschnitt beschreibt, wie Sie mit Methoden-Mocks arbeiten und Umgebungs- und globale Variablen ersetzen.

vi.fn ​

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

Erstellt einen Spy auf eine Funktion, kann aber auch ohne eine initialisiert werden. Jedes Mal, wenn eine Funktion aufgerufen wird, speichert sie ihre Aufrufargumente, Rückgabewerte und Instanzen. Sie können ihr Verhalten auch mit Methoden manipulieren. Wenn keine Funktion angegeben ist, gibt der Mock undefined zurück, wenn 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.isMockFunction ​

  • Typ: (fn: Function) => boolean

Prüft, ob ein gegebener Parameter eine Mock-Funktion ist. Wenn Sie TypeScript verwenden, wird auch der Typ eingeschränkt.

vi.clearAllMocks ​

Ruft .mockClear() für alle Spies auf. Dies löscht den Mock-Verlauf, setzt aber die Implementierung nicht auf die Standardimplementierung zurück.

vi.resetAllMocks ​

Ruft .mockReset() für alle Spies auf. Dies löscht den Mock-Verlauf und setzt die Implementierung auf eine leere Funktion zurück (die undefined zurückgibt).

vi.restoreAllMocks ​

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

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(). Es 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

Sie können vi.restoreAllMocks innerhalb von afterEach aufrufen (oder test.restoreMocks aktivieren), um alle Methoden auf ihre ursprünglichen Implementierungen zurückzusetzen. Dies stellt den ursprünglichen Objekt-Deskriptor wieder her, sodass Sie die Implementierung der Methode nicht mehr ä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. Dies 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 einer Umgebungsvariable in process.env und import.meta.env. Sie können den Wert wiederherstellen, indem Sie vi.unstubAllEnvs aufrufen.

ts
import { vi } from 'vitest';

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

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 Umgebungsvariablen nicht
import.meta.env.MODE === 'development';

TIP

Sie können den Wert auch einfach durch 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 es 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 wurde
process.env.NODE_ENV === 'development';
import.meta.env.NODE_ENV === 'development';

vi.stubGlobal ​

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

Ändert den Wert einer globalen Variable. Sie können ihren ursprünglichen Wert wiederherstellen, indem Sie vi.unstubAllGlobals aufrufen.

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 Zuweisung an globalThis oder window ändern (wenn Sie die jsdom- oder happy-dom-Umgebung verwenden). Allerdings können Sie 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 es 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 einen ReferenceError, da es nicht definiert ist
IntersectionObserver === undefined;

Fake-Timer ​

Dieser Abschnitt beschreibt, wie Sie mit Fake-Timern arbeiten.

vi.advanceTimersByTime ​

  • Typ: (ms: number) => Vitest

Diese Methode ruft jeden initiierten 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 initiierten Timer auf, bis die angegebene Anzahl von Millisekunden verstrichen ist oder die Warteschlange leer ist – je nachdem, was zuerst eintritt. Dies schließt asynchron gesetzte Timer ein.

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

Ruft den nächsten verfügbaren Timer auf. Nützlich, um Zusicherungen zwischen jedem Timer-Aufruf zu machen. Sie können die Aufrufe 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 er 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 es rückt die Timer um die Millisekunden vor, 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

Ruft die Anzahl der wartenden Timer ab.

vi.clearAllTimers ​

Entfernt alle Timer, die zur Ausführung geplant sind. Diese Timer werden in Zukunft nie ausgeführt.

vi.getMockedSystemTime ​

  • Typ: () => Date | null

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

vi.getRealSystemTime ​

  • Typ: () => number

Bei Verwendung von vi.useFakeTimers werden Date.now-Aufrufe gemockt. Wenn Sie die tatsächliche Zeit in Millisekunden abrufen müssen, können Sie diese Funktion aufrufen.

vi.runAllTicks ​

  • Typ: () => Vitest

Ruft jede Mikroaufgabe auf, die von process.nextTick in die Warteschlange gestellt wurde. Dies führt auch alle Mikroaufgaben aus, die von ihnen selbst geplant wurden.

vi.runAllTimers ​

  • Typ: () => Vitest

Diese Methode ruft jeden initiierten Timer auf, bis die Timer-Warteschlange leer ist. Das bedeutet, dass jeder Timer, der während runAllTimers aufgerufen wird, auch tatsächlich ausgelöst wird. Wenn Sie ein unendliches Intervall haben, wird nach 10.000 Versuchen ein Fehler ausgelöst (dies 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 initiierten Timer asynchron auf, bis die Timer-Warteschlange leer ist. Das bedeutet, dass jeder Timer, der während runAllTimersAsync aufgerufen wird, ausgelöst wird, auch asynchrone Timer. Wenn Sie ein unendliches Intervall haben, wird nach 10.000 Versuchen ein Fehler ausgelöst (dies kann mit fakeTimers.loopLimit konfiguriert werden).

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

await vi.runAllTimersAsync();

// log: result

vi.runOnlyPendingTimers ​

  • Typ: () => Vitest

Diese Methode ruft jeden Timer auf, der nach dem Aufruf von vi.useFakeTimers initiiert 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 initiiert wurde, asynchron auf, auch asynchrone. Sie löst keine Timer aus, 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, dass ein Benutzer die Systemuhr ändert. Dies wirkt sich auf datumsbezogene APIs wie hrtime, performance.now oder new Date() aus, löst jedoch keine Timer aus. Wenn Fake-Timer nicht aktiviert sind, mockt diese Methode nur Date.*-Aufrufe.

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

Akzeptiert dieselben String- und Zahlenargumente wie Date.

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 Timer zu mocken, müssen Sie diese Methode aufrufen. Sie umschließt alle weiteren Aufrufe an Timer (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 hängt, 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 nicht automatisch. Sie können es jedoch aktivieren, indem Sie die Option im Argument toFake angeben: vi.useFakeTimers({ toFake: ['nextTick'] }).

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 verworfen.

Verschiedenes ​

Eine Reihe nützlicher Hilfsfunktionen, die Vitest bereitstellt.

vi.waitFor ​

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

Wartet auf die erfolgreiche Ausführung des Callbacks. Wenn der Callback einen Fehler auslöst oder ein abgewiesenes Promise zurückgibt, wird weiter gewartet, bis er erfolgreich ist oder die Zeit abläuft.

Dies ist 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 started successfully', async () => {
  const server = createServer();

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

      console.log('Server started');
    },
    {
      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 exists in a DOM', async () => {
  // DOM-Befüllung starten
  populateDOMAsync();

  const element = await vi.waitFor(
    async () => {
      // versucht, das Element zu erhalten, 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 Prüf-Rückruf 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 Wert zurückgibt, der als falsch interpretiert wird (falsy), wird die nächste Prüfung fortgesetzt, bis ein Wert zurückgegeben wird, der als wahr interpretiert wird (truthy). Dies ist nützlich, wenn Sie warten müssen, bis etwas existiert, bevor Sie den nächsten Schritt ausführen.

Betrachten Sie das Beispiel unten. Wir können vi.waitUntil verwenden, um darauf zu warten, dass 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 render correctly', 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 verschoben, 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 aufzurufen.

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 tun.

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

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 Top-Level-Await nicht unterstützt:

ts
const promised = 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 dies die Konfiguration auf den ursprünglichen Zustand zurück.

Pager
Vorherige SeiteMock-Funktionen
Nächste Seiteexpect

Veröffentlicht unter der MIT-Lizenz.

Copyright (c) 2024 Mithril Contributors

https://v2.vitest.dev/api/vi

Veröffentlicht unter der MIT-Lizenz.

Copyright (c) 2024 Mithril Contributors