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

Warum Vitest

Erste Schritte

Features

Arbeitsbereich

Kommandozeilenschnittstelle

Testfilter

Reporter

Codeabdeckung (Coverage)

Snapshot

Mocking

Typen testen

Vitest UI

In-Source-Testing

Testkontext

Testumgebung

Erweiterung von Matchern

IDE-Integration

Debugging

Vergleiche mit anderen Test-Runnern

Migrationsleitfaden

Häufige Fehler

Profiling Test Performance

Leistungsverbesserung

Auf dieser Seite

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 ​

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

const businessHours = [9, 17];

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

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

  return { message: 'Error' };
}

describe('purchasing flow', () => {
  beforeEach(() => {
    // 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 ​

js
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 ​

  • Jests Mock-Funktionen

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.

ts
import { vi } from 'vitest';

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

vi.stubGlobal('IntersectionObserver', IntersectionObserverMock);

// 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:

  1. Einen Alias bereitstellen
ts
// vitest.config.js
export default {
  test: {
    alias: {
      '$app/forms': resolve('./mocks/forms.js'),
    },
  },
};
  1. Ein Plugin bereitstellen, das ein virtuelles Modul auflöst
ts
// 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:

ts
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):

ts
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:

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

vi.spyOn(mod, 'foo');

// exportiertes foo referenziert gemockte Methode
mod.foobar(mod.foo);
ts
// 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 ​

js
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:

ts
// wir können auch `import` verwenden, dann muss aber jeder Export explizit definiert werden

const { fs } = require('memfs');
module.exports = fs;
ts
// wir können auch `import` verwenden, dann muss aber jeder Export explizit definiert werden

const { fs } = require('memfs');
module.exports = fs.promises;
ts
// read-hello-world.js
import { readFileSync } from 'node:fs';

export function readHelloWorld(path) {
  return readFileSync(path);
}
ts
// 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:

js
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 ​

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

ts
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:

ts
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:

ts
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:

ts
// ./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:

ts
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:

ts
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:

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

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

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

TIP

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 ​

js
// some-path.js
export const getter = 'variable';
ts
// some-path.test.ts
import * as exports from './some-path.js';

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

Eine exportierte Funktion mocken ​

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

ts
// ./some-path.js
export function method() {}
ts
import { method } from './some-path.js';

vi.mock('./some-path.js', () => ({
  method: vi.fn(),
}));
  1. Beispiel mit vi.spyOn:
ts
import * as exports from './some-path.js';

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

Eine exportierte Klassenimplementierung mocken ​

  1. Beispiel mit vi.mock und .prototype:
ts
// ./some-path.ts
export class SomeClass {}
ts
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
  1. Beispiel mit vi.spyOn:
ts
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 ​

  1. Beispiel mit Cache:
ts
// some-path.ts
export function useObject() {
  return { method: () => true };
}
ts
// useObject.js
import { useObject } from './some-path.js';

const obj = useObject();
obj.method();
ts
// 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 ​

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

vi.mock(import('./some-path.js'), async importOriginal => {
  const mod = await importOriginal();
  return {
    ...mod,
    mocked: vi.fn(),
  };
});
original(); // 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.

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

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

import.meta.env mocken ​

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

ts
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');
});
  1. Wenn Sie die Werte automatisch zurücksetzen möchten, können Sie den vi.stubEnv-Helfer mit aktivierter Konfigurationsoption unstubEnvs verwenden (oder vi.unstubAllEnvs manuell in einem beforeEach-Hook aufrufen):
ts
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');
});
ts
// vitest.config.ts
export default defineConfig({
  test: {
    unstubEnvs: true,
  },
});
Pager
Vorherige SeiteSnapshot
Nächste SeiteTypen testen

Veröffentlicht unter der MIT-Lizenz.

Copyright (c) 2024 Mithril Contributors

https://v2.vitest.dev/guide/mocking

Veröffentlicht unter der MIT-Lizenz.

Copyright (c) 2024 Mithril Contributors