Mocking
Beim Schreiben von Tests ist es oft notwendig, eine "simulierte" Version eines internen oder externen Dienstes zu erstellen. Dies wird allgemein als Mocking bezeichnet. Vitest stellt hierfür Hilfsfunktionen über den vi-Helfer bereit. Sie können import { vi } from 'vitest'
importieren oder global darauf zugreifen (sofern die globale Konfiguration aktiviert ist).
WARNING
Denken Sie immer daran, Mocks vor oder nach jedem Testlauf zurückzusetzen oder wiederherzustellen, um Änderungen des Mock-Zustands zwischen den Läufen aufzuheben! Weitere Informationen finden Sie in der Dokumentation zu mockReset
.
Wenn Sie direkt einsteigen möchten, schauen Sie sich den API-Bereich an; andernfalls lesen Sie weiter, um tiefer in die Welt des Mockings einzutauchen.
Datumsangaben
Manchmal müssen Sie das Datum steuern, um Konsistenz beim Testen zu gewährleisten. Vitest verwendet das Paket @sinonjs/fake-timers
zur Manipulation von Timern und des Systemdatums. Mehr über die spezifische API finden Sie detailliert hier.
Beispiel
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(() => {
// Vitest mitteilen, dass wir gemockte Zeit verwenden
vi.useFakeTimers();
});
afterEach(() => {
// Datum nach jedem Testlauf wiederherstellen
vi.useRealTimers();
});
it('allows purchases within business hours', () => {
// Stunde innerhalb der Geschäftszeiten einstellen
const date = new Date(2000, 1, 1, 13);
vi.setSystemTime(date);
// Zugriff auf Date.now() führt zum oben eingestellten Datum
expect(purchase()).toEqual({ message: 'Success' });
});
it('disallows purchases outside of business hours', () => {
// Stunde außerhalb der Geschäftszeiten einstellen
const date = new Date(2000, 1, 1, 19);
vi.setSystemTime(date);
// Zugriff auf Date.now() führt zum oben eingestellten Datum
expect(purchase()).toEqual({ message: 'Error' });
});
});
Funktionen
Das Mocken von Funktionen lässt sich in zwei verschiedene Kategorien unterteilen: Spionieren und Mocken.
Manchmal müssen Sie nur überprüfen, ob eine bestimmte Funktion aufgerufen wurde (und möglicherweise welche Argumente übergeben wurden). In diesen Fällen genügt ein Spy, den Sie direkt mit vi.spyOn()
verwenden können (lesen Sie hier mehr).
Spies können Ihnen jedoch nur dabei helfen, Funktionen zu spionieren, sie sind jedoch nicht in der Lage, die Implementierung dieser Funktionen zu ändern. Wenn wir jedoch eine gefälschte (oder gemockte) Version einer Funktion erstellen müssen, können wir vi.fn()
verwenden (lesen Sie hier mehr).
Wir verwenden Tinyspy als Grundlage für das Mocken von Funktionen, haben jedoch einen eigenen Wrapper, um es jest
-kompatibel zu machen. Sowohl vi.fn()
als auch vi.spyOn()
teilen sich dieselben Methoden, allerdings ist nur das von vi.fn()
zurückgegebene Ergebnis aufrufbar.
Beispiel
import { afterEach, describe, expect, it, vi } from 'vitest';
const messages = {
items: [
{ message: 'Simple test message', from: 'Testman' },
// ...
],
getLatest, // kann auch ein Getter oder Setter sein, sofern unterstützt
};
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);
});
});
Mehr
Globale Variablen
Sie können globale Variablen, die in Umgebungen wie jsdom
oder node
nicht vorhanden sind, mithilfe des Hilfsprogramms vi.stubGlobal
mocken. Es wird den Wert der globalen Variable in ein globalThis
-Objekt setzen.
import { vi } from 'vitest';
const IntersectionObserverMock = vi.fn(() => ({
disconnect: vi.fn(),
observe: vi.fn(),
takeRecords: vi.fn(),
unobserve: vi.fn(),
}));
vi.stubGlobal('IntersectionObserver', IntersectionObserverMock);
// jetzt können Sie darauf als `IntersectionObserver` oder `window.IntersectionObserver` zugreifen
Module
Mock-Module wirken sich auf Drittanbieter-Bibliotheken aus, die in anderem Code aufgerufen werden, sodass Sie Argumente und Ausgaben testen oder sogar deren Implementierung neu deklarieren können.
Weitere detaillierte API-Beschreibungen finden Sie im vi.mock()
API-Abschnitt.
Automocking-Algorithmus
Wenn Ihr Code ein gemocktes Modul importiert, ohne eine zugehörige __mocks__
-Datei oder factory
für dieses Modul, wird Vitest das Modul selbst mocken, indem es es aufruft und alle Exporte mockt.
Es gelten die folgenden Prinzipien:
- Alle Arrays werden geleert
- Alle Primitiven und Sammlungen bleiben unverändert
- Alle Objekte werden tief geklont
- Alle Instanzen von Klassen und deren Prototypen werden tief geklont
Virtuelle Module
Vitest unterstützt das Mocken von Vite virtuellen Modulen. Es funktioniert anders als virtuelle Module in Jest behandelt werden. Anstatt virtual: true
an eine vi.mock
-Funktion zu übergeben, müssen Sie Vite mitteilen, dass das Modul existiert, andernfalls schlägt es während des Parsens fehl. Dies können Sie auf verschiedene Weisen tun:
- Einen Alias bereitstellen
// vitest.config.js
export default {
test: {
alias: {
'$app/forms': resolve('./mocks/forms.js'),
},
},
};
- Ein Plugin bereitstellen, das ein virtuelles Modul auflöst
// vitest.config.js
export default {
plugins: [
{
name: 'virtual-modules',
resolveId(id) {
if (id === '$app/forms') {
return 'virtual:$app/forms';
}
},
},
],
};
Der Vorteil des zweiten Ansatzes ist, dass Sie dynamisch verschiedene virtuelle Moduleinträge erstellen können. Wenn Sie mehrere virtuelle Module in eine einzige Datei umleiten, werden alle von vi.mock
betroffen sein. Stellen Sie daher sicher, eindeutige Bezeichner zu verwenden.
Mocking-Fallstricke
Beachten Sie, dass es nicht möglich ist, Methodenaufrufe zu mocken, die innerhalb derselben Datei von anderen Methoden aufgerufen werden. Zum Beispiel in diesem Code:
export function foo() {
return 'foo';
}
export function foobar() {
return `${foo()}bar`;
}
Es ist nicht möglich, die foo
-Methode extern zu mocken, da sie direkt referenziert wird. Dieser Code wird also keine Auswirkung auf den foo
-Aufruf innerhalb von foobar
haben (aber er wirkt sich auf den foo
-Aufruf in anderen Modulen aus):
import { vi } from 'vitest';
import * as mod from './foobar.js';
// dies wirkt sich nur auf "foo" außerhalb des ursprünglichen Moduls aus
vi.spyOn(mod, 'foo');
vi.mock('./foobar.js', async importOriginal => {
return {
...(await importOriginal<typeof import('./foobar.js')>()),
// dies wirkt sich nur auf "foo" außerhalb des ursprünglichen Moduls aus
foo: () => 'mocked',
};
});
Sie können dieses Verhalten bestätigen, indem Sie die Implementierung direkt der foobar
-Methode bereitstellen:
// foobar.test.js
import * as mod from './foobar.js';
vi.spyOn(mod, 'foo');
// exportiertes foo referenziert gemockte Methode
mod.foobar(mod.foo);
// foobar.js
export function foo() {
return 'foo';
}
export function foobar(injectedFoo) {
return injectedFoo === foo; // false
}
Dies ist das beabsichtigte Verhalten. Es ist normalerweise ein Zeichen für schlechten Code, wenn Mocking auf diese Weise eingesetzt wird. Erwägen Sie, Ihren Code in mehrere Dateien umzustrukturieren oder Ihre Anwendungsarchitektur durch Techniken wie Dependency Injection zu verbessern.
Beispiel
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
import { Client } from 'pg';
import { failure, success } from './handlers.js';
// todos abrufen
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 });
});
});
Dateisystem
Das Mocken des Dateisystems stellt sicher, dass die Tests nicht vom tatsächlichen Dateisystem abhängen, was sie zuverlässiger und vorhersehbarer macht. Diese Isolation trägt dazu bei, Nebenwirkungen von früheren Tests zu vermeiden. Sie ermöglicht das Testen von Fehlerbedingungen und Grenzfällen, die mit einem tatsächlichen Dateisystem schwierig oder unmöglich zu reproduzieren wären, wie z. B. Berechtigungsprobleme, volle Festplatten oder Lese-/Schreibfehler.
Vitest bietet keine Dateisystem-Mocking-API standardmäßig. Sie können vi.mock
verwenden, um das fs
-Modul manuell zu mocken, was jedoch schwer zu pflegen ist. Stattdessen empfehlen wir die Verwendung von memfs
, das dies für Sie übernimmt. memfs
erstellt ein In-Memory-Dateisystem, das Dateisystemoperationen simuliert, ohne die tatsächliche Festplatte zu berühren. Dieser Ansatz ist schnell und sicher und verhindert potenzielle Nebenwirkungen auf das reale Dateisystem.
Beispiel
Um jeden fs
-Aufruf automatisch an memfs
umzuleiten, können Sie __mocks__/fs.cjs
und __mocks__/fs/promises.cjs
-Dateien im Projektstammverzeichnis erstellen:
// wir können auch `import` verwenden, dann muss aber jeder Export explizit definiert werden
const { fs } = require('memfs');
module.exports = fs;
// wir können auch `import` verwenden, dann muss aber jeder Export explizit definiert werden
const { fs } = require('memfs');
module.exports = fs.promises;
// read-hello-world.js
import { readFileSync } from 'node:fs';
export function readHelloWorld(path) {
return readFileSync(path);
}
// hello-world.test.js
import { beforeEach, expect, it, vi } from 'vitest';
import { fs, vol } from 'memfs';
import { readHelloWorld } from './read-hello-world.js';
// Vitest anweisen, die fs-Mock-Implementierung aus dem __mocks__-Ordner zu verwenden
// dies kann in einer Setup-Datei erfolgen, wenn fs immer gemockt werden soll
vi.mock('node:fs');
vi.mock('node:fs/promises');
beforeEach(() => {
// den Zustand des In-Memory-Dateisystems zurücksetzen
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', () => {
// Sie können vol.fromJSON verwenden, um mehrere Dateien zu definieren
vol.fromJSON(
{
'./dir1/hw.txt': 'hello dir1',
'./dir2/hw.txt': 'hello dir2',
},
// Standard-CWD
'/tmp'
);
expect(readHelloWorld('/tmp/dir1/hw.txt')).toBe('hello dir1');
expect(readHelloWorld('/tmp/dir2/hw.txt')).toBe('hello dir2');
});
Anfragen
Da Vitest in Node läuft, ist das Mocken von Netzwerkanfragen herausfordernd; Web-APIs sind nicht verfügbar, daher benötigen wir etwas, das das Netzwerkverhalten für uns nachahmt. Wir empfehlen Mock Service Worker, um dies zu erreichen. Es ermöglicht Ihnen, sowohl REST
- als auch GraphQL
-Netzwerkanfragen zu mocken und ist dabei Framework-agnostisch.
Mock Service Worker (MSW) funktioniert, indem es die Anfragen abfängt, die von Ihren Tests gestellt werden, sodass Sie es verwenden können, ohne Ihren Anwendungscode zu ändern. Im Browser wird hierfür die Service Worker API verwendet. In Node.js und für Vitest kommt die Bibliothek @mswjs/interceptors
zum Einsatz. Um mehr über MSW zu erfahren, lesen Sie deren Einführung.
Konfiguration
Sie können es wie unten in Ihrer Setup-Datei verwenden:
import { afterAll, afterEach, beforeAll } from 'vitest';
import { setupServer } from 'msw/node';
import { graphql, 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 graphqlHandlers = [
graphql.query('ListPosts', () => {
return HttpResponse.json({
data: { posts },
});
}),
];
const server = setupServer(...restHandlers, ...graphqlHandlers);
// Server vor allen Tests starten
beforeAll(() => server.listen({ onUnhandledRequest: 'error' }));
// Server nach allen Tests schließen
afterAll(() => server.close());
// Handler nach jedem Test zurücksetzen (wichtig für die Testisolation)
afterEach(() => server.resetHandlers());
Die Konfiguration des Servers mit
onUnhandleRequest: 'error'
stellt sicher, dass ein Fehler ausgelöst wird, sobald eine Anfrage keinen entsprechenden Anfrage-Handler besitzt.
Mehr
Es gibt noch viel mehr zu MSW. Sie können auf Cookies und Abfrageparameter zugreifen, Mock-Fehlerantworten definieren und vieles mehr! Um alles zu sehen, was Sie mit MSW tun können, lesen Sie deren Dokumentation.
Timer
Wenn wir Code testen, der Timeouts oder Intervalle enthält, können wir unsere Tests beschleunigen, indem wir "gefälschte" Timer verwenden, die Aufrufe an setTimeout
und setInterval
mocken, anstatt die Tests warten oder in einen Timeout laufen zu lassen.
Weitere detaillierte API-Beschreibungen finden Sie im vi.useFakeTimers
API-Abschnitt.
Beispiel
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
function executeAfterTwoHours(func) {
setTimeout(func, 1000 * 60 * 60 * 2); // 2 Stunden
}
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);
// um 2ms vorrücken löst die Funktion nicht aus
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);
});
});
Klassen
Sie können eine ganze Klasse mit einem einzigen vi.fn
-Aufruf mocken – da alle Klassen auch Funktionen sind, funktioniert dies ohne Weiteres. Beachten Sie, dass Vitest derzeit das new
-Schlüsselwort nicht unterstützt, sodass new.target
im Funktionskörper immer undefined
ist.
class Dog {
name: string;
constructor(name: string) {
this.name = name;
}
static getType(): string {
return 'animal';
}
speak(): string {
return 'bark!';
}
isHungry() {}
feed() {}
}
Wir können diese Klasse mit ES5-Funktionen neu erstellen:
const Dog = vi.fn(function (name) {
this.name = name;
});
// beachten Sie, dass statische Methoden direkt auf der Funktion gemockt werden,
// und nicht auf der Instanz der Klasse
Dog.getType = vi.fn(() => 'mocked animal');
// die Methoden "speak" und "feed" für jede Instanz einer Klasse mocken
// alle `new Dog()`-Instanzen erben diese Spies
Dog.prototype.speak = vi.fn(() => 'loud bark!');
Dog.prototype.feed = vi.fn();
WANN ZU VERWENDEN?
Im Allgemeinen würden Sie eine Klasse wie diese innerhalb der Modulfactory neu erstellen, wenn die Klasse aus einem anderen Modul erneut exportiert wird:
import { Dog } from './dog.js';
vi.mock(import('./dog.js'), () => {
const Dog = vi.fn();
Dog.prototype.feed = vi.fn();
// ... andere Mocks
return { Dog };
});
Diese Methode kann auch verwendet werden, um eine Instanz einer Klasse an eine Funktion zu übergeben, die dieselbe Schnittstelle akzeptiert:
// ./src/feed.ts
function feed(dog: Dog) {
// ...
}
// ./tests/dog.test.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);
});
Wenn wir nun eine neue Instanz der Dog
-Klasse erstellen, ist ihre speak
-Methode (neben feed
) bereits gemockt:
const dog = new Dog('Cooper');
dog.speak(); // loud bark!
// Sie können integrierte Assertions verwenden, um die Gültigkeit des Aufrufs zu überprüfen
expect(dog.speak).toHaveBeenCalled();
Wir können den Rückgabewert für eine bestimmte Instanz neu zuweisen:
const dog = new Dog('Cooper');
// "vi.mocked" ist ein Typ-Helfer, da
// TypeScript nicht weiß, dass Dog eine gemockte Klasse ist,
// es jede Funktion in einen MockInstance<T>-Typ umwandelt,
// ohne zu überprüfen, ob die Funktion ein Mock ist
vi.mocked(dog.speak).mockReturnValue('woof woof');
dog.speak(); // woof woof
Um eine Eigenschaft zu mocken, können wir die Methode vi.spyOn(dog, 'name', 'get')
verwenden. Dies ermöglicht die Verwendung von Spy-Assertions auf der gemockten Eigenschaft:
const dog = new Dog('Cooper');
const nameSpy = vi.spyOn(dog, 'name', 'get').mockReturnValue('Max');
expect(dog.name).toBe('Max');
expect(nameSpy).toHaveBeenCalledTimes(1);
TIP
Sie können auch Getter und Setter mit derselben Methode ausspionieren.
Spickzettel
INFO
vi
in den folgenden Beispielen wird direkt von vitest
importiert. Sie können es auch global verwenden, wenn Sie globals
in Ihrer Konfiguration auf true
setzen.
Ich möchte…
Exportierte Variablen mocken
// some-path.js
export const getter = 'variable';
// some-path.test.ts
import * as exports from './some-path.js';
vi.spyOn(exports, 'getter', 'get').mockReturnValue('mocked');
Eine exportierte Funktion mocken
- Beispiel mit
vi.mock
:
WARNING
Vergessen Sie nicht, dass ein vi.mock
-Aufruf an den Anfang der Datei nach oben verschoben wird. Er wird immer vor allen Importen ausgeführt.
// ./some-path.js
export function method() {}
import { method } from './some-path.js';
vi.mock('./some-path.js', () => ({
method: vi.fn(),
}));
- Beispiel mit
vi.spyOn
:
import * as exports from './some-path.js';
vi.spyOn(exports, 'method').mockImplementation(() => {});
Eine exportierte Klassenimplementierung mocken
- Beispiel mit
vi.mock
und.prototype
:
// ./some-path.ts
export class SomeClass {}
import { SomeClass } from './some-path.js';
vi.mock(import('./some-path.js'), () => {
const SomeClass = vi.fn();
SomeClass.prototype.someMethod = vi.fn();
return { SomeClass };
});
// SomeClass.mock.instances wird Instanzen von SomeClass enthalten
- Beispiel mit
vi.spyOn
:
import * as mod from './some-path.js';
const SomeClass = vi.fn();
SomeClass.prototype.someMethod = vi.fn();
vi.spyOn(mod, 'SomeClass').mockImplementation(SomeClass);
Ein von einer Funktion zurückgegebenes Objekt ausspionieren
- Beispiel mit Cache:
// some-path.ts
export function useObject() {
return { method: () => true };
}
// useObject.js
import { useObject } from './some-path.js';
const obj = useObject();
obj.method();
// useObject.test.js
import { useObject } from './some-path.js';
vi.mock(import('./some-path.js'), () => {
let _cache;
const useObject = () => {
if (!_cache) {
_cache = {
method: vi.fn(),
};
}
// jetzt wird bei jedem Aufruf von useObject()
// dieselbe Objektreferenz zurückgegeben
return _cache;
};
return { useObject };
});
const obj = useObject();
// obj.method wurde innerhalb von some-path aufgerufen
expect(obj.method).toHaveBeenCalled();
Teil eines Moduls mocken
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(); // hat ursprüngliches Verhalten
mocked(); // ist eine Spy-Funktion
WARNING
Vergessen Sie nicht, dass dies nur den externen Zugriff mockt. In diesem Beispiel, wenn original
intern mocked
aufruft, wird es immer die im Modul definierte Funktion aufrufen, und nicht die in der Mock-Factory definierte.
Das aktuelle Datum mocken
Um die Zeit von Date
zu mocken, können Sie die Hilfsfunktion vi.setSystemTime
verwenden. Dieser Wert wird nicht automatisch zwischen den einzelnen Tests zurückgesetzt.
Beachten Sie, dass die Verwendung von vi.useFakeTimers
auch die Zeit von Date
ändert.
const mockDate = new Date(2022, 0, 1);
vi.setSystemTime(mockDate);
const now = new Date();
expect(now.valueOf()).toBe(mockDate.valueOf());
// gemockte Zeit zurücksetzen
vi.useRealTimers();
Eine globale Variable mocken
Sie können eine globale Variable setzen, indem Sie globalThis
einen Wert zuweisen oder den Hilfsdienst vi.stubGlobal
verwenden. Bei Verwendung von vi.stubGlobal
wird der Wert nicht automatisch zwischen verschiedenen Tests zurückgesetzt, es sei denn, Sie aktivieren die Konfigurationsoption unstubGlobals
oder rufen vi.unstubAllGlobals
auf.
vi.stubGlobal('__VERSION__', '1.0.0');
expect(__VERSION__).toBe('1.0.0');
import.meta.env
mocken
- Um eine Umgebungsvariable zu ändern, können Sie ihr einfach einen neuen Wert zuweisen.
WARNING
Der Wert der Umgebungsvariable wird nicht automatisch zwischen verschiedenen Tests zurückgesetzt.
import { beforeEach, expect, it } from 'vitest';
// vor dem Ausführen der Tests ist "VITE_ENV" "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');
});
- Wenn Sie die Werte automatisch zurücksetzen möchten, können Sie den
vi.stubEnv
-Helfer mit aktivierter KonfigurationsoptionunstubEnvs
verwenden (odervi.unstubAllEnvs
manuell in einembeforeEach
-Hook aufrufen):
import { expect, it, vi } from 'vitest';
// vor dem Ausführen der Tests ist "VITE_ENV" "test"
import.meta.env.VITE_ENV === 'test';
it('changes value', () => {
vi.stubEnv('VITE_ENV', 'staging');
expect(import.meta.env.VITE_ENV).toBe('staging');
});
it('der Wert wird vor dem Ausführen eines weiteren Tests wiederhergestellt', () => {
expect(import.meta.env.VITE_ENV).toBe('test');
});
// vitest.config.ts
export default defineConfig({
test: {
unstubEnvs: true,
},
});