Skip to content
Vitest 3
Main Navigation Przewodnik & APIKonfiguracjaTryb przeglądarkiZaawansowane API
3.2.0
2.1.9
1.6.1
0.34.6

Polski

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

Polski

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

Wygląd

Sidebar Navigation

Wprowadzenie

Dlaczego Vitest

Pierwsze kroki

Funkcje

Konfiguracja Vitest

API

Dokumentacja API testowego

Funkcje Mock

Vi

expect

expectTypeOf

assert

assertType

Przewodnik

Interfejs Wiersza Poleceń

Filtrowanie testów

Projekty testowe

Reportery

Pokrycie kodu

Migawki

Mockowanie

Równoległość

Typy testów

Interfejs użytkownika Vitest

Testy w kodzie źródłowym

Kontekst Testu

Adnotacje testowe

Środowisko testowe

Rozszerzanie matcherów

Integracje z IDE

Debugowanie

Typowe błędy

Przewodnik migracji

Migracja do Vitest 3.0

Migracja z Jest

Wydajność

Profilowanie wydajności testów

Poprawa wydajności

Tryb przeglądarkowy

Zaawansowane API

Porównania z innymi narzędziami do uruchamiania testów

Na tej stronie

Vi ​

Vitest udostępnia funkcje pomocnicze za pośrednictwem swojego pomocnika vi. Możesz uzyskać do niego dostęp globalnie (gdy włączona jest konfiguracja globalna) lub zaimportować go bezpośrednio z vitest:

js
import { vi } from 'vitest';

Mockowanie modułów ​

Ta sekcja opisuje API, którego możesz używać podczas mockowania modułu. Pamiętaj, że Vitest nie obsługuje mockowania modułów importowanych za pomocą require().

vi.mock ​

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

Zastępuje wszystkie zaimportowane moduły z podanej ścieżki innym modułem. Możesz używać skonfigurowanych aliasów Vite w obrębie ścieżki. Wywołanie vi.mock jest przenoszone na górę (hoisted), więc nie ma znaczenia, gdzie je wywołasz. Zawsze zostanie wykonane przed wszystkimi importami. Jeśli potrzebujesz odwołać się do zmiennych spoza jego zakresu, możesz je zdefiniować w vi.hoisted i użyć ich w vi.mock.

WARNING

vi.mock działa tylko dla modułów, które zostały zaimportowane za pomocą słowa kluczowego import. Nie działa z require.

Aby przenieść vi.mock na górę (hoist), Vitest statycznie analizuje twoje pliki. Oznacza to, że vi, które nie zostało bezpośrednio zaimportowane z pakietu vitest (na przykład z jakiegoś pliku narzędziowego), nie może być wykorzystane. Użyj vi.mock z vi zaimportowanym z vitest lub włącz opcję konfiguracyjną globals.

Vitest nie będzie mockować modułów, które zostały zaimportowane w pliku konfiguracyjnym, ponieważ w momencie uruchamiania pliku testowego są już one w pamięci podręcznej. Możesz wywołać vi.resetModules() w vi.hoisted, aby wyczyścić wszystkie pamięci podręczne modułów przed uruchomieniem pliku testowego.

Jeśli funkcja fabrykująca (factory) jest zdefiniowana, wszystkie importy zwracają jej wynik. Vitest wywołuje funkcję fabrykującą tylko raz i przechowuje wyniki w pamięci podręcznej dla wszystkich kolejnych importów, dopóki nie zostanie wywołane vi.unmock lub vi.doUnmock.

W przeciwieństwie do jest, funkcja fabrykująca może być asynchroniczna. Możesz użyć vi.importActual lub pomocnika z funkcją fabrykującą przekazaną jako pierwszy argument i uzyskać oryginalny moduł wewnątrz.

Możesz również podać obiekt z właściwością spy zamiast funkcji fabrykującej. Jeśli spy jest true, Vitest automatycznie mockuje moduł jak zwykle, ale nie nadpisuje implementacji eksportów. Jest to przydatne, jeśli chcesz tylko sprawdzić, czy wyeksportowana metoda została poprawnie wywołana przez inną metodę.

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

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

// wywołuje oryginalną implementację,
// ale pozwala na późniejsze sprawdzenie zachowania
const result = calculator(1, 2);

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

Vitest obsługuje również użycie obietnicy modułu zamiast ciągu znaków w metodach vi.mock i vi.doMock dla lepszego wsparcia IDE. Gdy plik zostanie przeniesiony, ścieżka zostanie zaktualizowana, a importOriginal automatycznie odziedziczy typ. Użycie tej sygnatury wymusi również, aby typ zwracany przez funkcję fabrykującą był zgodny z oryginalnym modułem (zachowując eksporty opcjonalnie).

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 jest dedukowany
  //    ^?
  return {
    ...mod,
    // zastąp niektóre eksporty
    total: vi.fn(),
  };
});

Pod maską Vitest nadal operuje na ciągu znaków, a nie na obiekcie modułu.

Jeśli używasz TypeScript z aliasami paths skonfigurowanymi w tsconfig.json jednak, kompilator nie będzie w stanie poprawnie rozwiązać typów importu. Aby to zadziałało, upewnij się, że zastąpisz wszystkie zaaliasowane importy ich odpowiednimi względnymi ścieżkami. Np. użyj import('./path/to/module.js') zamiast import('@/module').

WARNING

vi.mock jest przenoszone na górę pliku (hoisted). Oznacza to, że niezależnie od tego, gdzie je napiszesz (czy to w beforeEach, czy w test), zostanie ono faktycznie wywołane wcześniej.

Oznacza to również, że nie możesz używać żadnych zmiennych w funkcji fabrykującej, które są zdefiniowane poza funkcją fabrykującą.

Jeśli musisz użyć zmiennych w funkcji fabrykującej, spróbuj vi.doMock. Działa tak samo, ale nie jest przenoszone na górę. Pamiętaj, że ma wpływ tylko na kolejne importy.

Możesz również odwołać się do zmiennych zdefiniowanych przez metodę vi.hoisted, jeśli została zadeklarowana przed vi.mock:

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

Jeśli mockujesz moduł z domyślnym eksportem, musisz podać klucz default w zwróconym obiekcie funkcji fabrykującej. Jest to specyficzna dla modułów ES uwaga; dlatego dokumentacja jest może się różnić, ponieważ jest używa modułów CommonJS. Na przykład:

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

Jeśli obok mockowanego pliku znajduje się folder __mocks__, a funkcja fabrykująca nie jest dostarczona, Vitest spróbuje znaleźć plik o tej samej nazwie w podfolderze __mocks__ i użyć go jako faktycznego modułu. Jeśli mockujesz zależność, Vitest spróbuje znaleźć folder __mocks__ w katalogu głównym projektu (domyślnie process.cwd()). Możesz wskazać Vitest, gdzie znajdują się zależności, za pomocą opcji konfiguracyjnej deps.moduleDirectories.

Na przykład, masz taką strukturę plików:

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

Jeśli wywołasz vi.mock w pliku testowym bez podania funkcji fabrykującej lub opcji, znajdzie on plik w folderze __mocks__ do użycia jako moduł:

ts
import { vi } from 'vitest';

// axios to domyślny eksport z `__mocks__/axios.js`
import axios from 'axios';

// increment to nazwany eksport z `src/__mocks__/increment.js`
import { increment } from '../increment.js';

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

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

WARNING

Pamiętaj, że jeśli nie wywołasz vi.mock, moduły nie będą automatycznie mockowane. Aby odtworzyć zachowanie automockowania Jest, możesz wywołać vi.mock dla każdego wymaganego modułu w setupFiles.

Jeśli nie ma folderu __mocks__ ani dostarczonej funkcji fabrykującej, Vitest zaimportuje oryginalny moduł i automatycznie mockuje wszystkie jego eksporty. Zasady zastosowane, patrz algorytm.

vi.doMock ​

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

To samo co vi.mock, ale nie jest przenoszone na górę pliku, więc możesz odwoływać się do zmiennych w globalnym zakresie pliku. Następny dynamiczny import modułu zostanie zmockowany.

WARNING

Ta funkcja nie zmockuje modułów, które zostały zaimportowane przed jej wywołaniem. Nie zapominaj, że wszystkie statyczne importy w ESM są zawsze przenoszone na górę, więc umieszczenie tego przed statycznym importem nie spowoduje, że zostanie wywołane przed importem:

ts
vi.doMock('./increment.js'); // to zostanie wywołane _po_ instrukcji importu

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

// moduł nie jest mockowany, ponieważ vi.doMock nie zostało jeszcze wywołane
increment(1) === 2;

let mockedIncrement = 100;

beforeEach(() => {
  // możesz uzyskać dostęp do zmiennych wewnątrz funkcji fabrykującej
  vi.doMock('./increment.js', () => ({ increment: () => ++mockedIncrement }));
});

test('importowanie następnego modułu importuje zmockowany', async () => {
  // oryginalny import NIE BYŁ MOCKOWANY, ponieważ vi.doMock jest wykonywane PO importach
  expect(increment(1)).toBe(2);
  const { increment: mockedIncrement } = await import('./increment.js');
  // nowy dynamiczny import zwraca zmockowany moduł
  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>

Pomocnik typowania dla TypeScript. Po prostu zwraca przekazany mu obiekt.

Gdy partial jest true, oczekuje zwrócenia Partial<T>. Domyślnie spowoduje to, że TypeScript będzie traktował tylko wartości pierwszego poziomu jako mockowane. Możesz przekazać { deep: true } jako drugi argument, aby poinformować TypeScript, że cały obiekt jest mockowany, jeśli faktycznie tak jest.

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 równa się 10', async () => {
  vi.mocked(example.add).mockReturnValue(10);
  expect(example.add(1, 1)).toBe(10);
});

test('mockowana wartość zwracana z tylko częściowo poprawnym typowaniem', 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 }) // to jest błąd typu
});

vi.importActual ​

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

Importuje moduł, omijając wszystkie sprawdzenia, czy powinien zostać zmockowany. Może być przydatne, jeśli chcesz częściowo mockować moduł.

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

Importuje moduł ze wszystkimi jego właściwościami (w tym zagnieżdżonymi właściwościami) zmockowanymi. Przestrzega tych samych zasad, co vi.mock. Zasady zastosowane, patrz algorytm.

vi.unmock ​

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

Usuwa moduł z rejestru mockowanych modułów. Wszystkie wywołania importu będą zwracać oryginalny moduł, nawet jeśli był wcześniej mockowany. To wywołanie jest przenoszone na górę pliku, więc odmockuje tylko moduły, które zostały zdefiniowane na przykład w setupFiles.

vi.doUnmock ​

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

To samo co vi.unmock, ale nie jest przenoszone na górę pliku. Następny import modułu spowoduje zaimportowanie oryginalnego modułu zamiast mocka. To nie odmockuje wcześniej zaimportowanych modułów.

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

// increment jest już zmockowany, ponieważ vi.mock jest przeniesione na górę
increment(1) === 100;

// to jest przeniesione na górę, a funkcja fabrykująca jest wywoływana przed importem w linii 1
vi.mock('./increment.js', () => ({ increment: () => 100 }));

// wszystkie wywołania są zmockowane, a `increment` zawsze zwraca 100
increment(1) === 100;
increment(30) === 100;

// to nie jest przenoszone na górę, więc inny import zwróci niemockowany moduł
vi.doUnmock('./increment.js');

// to NADAL zwraca 100, ponieważ `vi.doUnmock` nie ponownie ocenia modułu
increment(1) === 100;
increment(30) === 100;

// następny import jest niemockowany, teraz `increment` to oryginalna funkcja, która zwraca count + 1
const { increment: unmockedIncrement } = await import('./increment.js');

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

vi.resetModules ​

  • Typ: () => Vitest

Resetuje rejestr modułów, czyszcząc pamięć podręczną dla wszystkich modułów. Pozwala to na ponowne wykonanie modułów po ponownym zaimportowaniu. Importy najwyższego poziomu nie mogą być ponownie wykonane. Może być przydatne do izolowania modułów, gdzie lokalny stan powoduje konflikty między testami.

ts
import { vi } from 'vitest';

import { data } from './data.js'; // Nie zostanie ponownie wykonane przed każdym testem

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

test('zmień stan', async () => {
  const mod = await import('./some/path.js'); // Zostanie ponownie wykonane
  mod.changeLocalState('nowa wartość');
  expect(mod.getLocalState()).toBe('nowa wartość');
});

test('moduł ma stary stan', async () => {
  const mod = await import('./some/path.js'); // Zostanie ponownie wykonane
  expect(mod.getLocalState()).toBe('stara wartość');
});

WARNING

Nie resetuje rejestru mocków. Aby wyczyścić rejestr mocków, użyj vi.unmock lub vi.doUnmock.

vi.dynamicImportSettled ​

Czeka na załadowanie wszystkich importów. Przydatne, jeśli masz synchroniczne wywołanie, które rozpoczyna importowanie modułu, na którego załadowanie nie możesz w inny sposób poczekać.

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

// nie można śledzić importu, ponieważ Promise nie jest zwracany
function renderComponent() {
  import('./component.js').then(({ render }) => {
    render();
  });
}

test('operacje są rozwiązane', async () => {
  renderComponent();
  await vi.dynamicImportSettled();
  expect(document.querySelector('.component')).not.toBeNull();
});

TIP

Jeśli podczas dynamicznego importu zostanie zainicjowany inny dynamiczny import, ta metoda będzie czekać, aż wszystkie zostaną rozwiązane.

Ta metoda będzie również czekać na następny tick setTimeout po rozwiązaniu importu, więc wszystkie synchroniczne operacje powinny zostać zakończone do momentu jej rozwiązania.

Mockowanie funkcji i obiektów ​

Ta sekcja opisuje, jak pracować z mockami metod i zastępować zmienne środowiskowe i globalne.

vi.fn ​

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

Tworzy funkcję szpiegującą (spy) dla funkcji, choć może być zainicjowana bez niej. Za każdym razem, gdy funkcja jest wywoływana, przechowuje jej argumenty wywołania, wartości zwracane i instancje. Ponadto, możesz manipulować jej zachowaniem za pomocą metod. Jeśli nie podano funkcji, mock zwróci undefined po wywołaniu.

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>

Głęboko mockuje właściwości i metody danego obiektu w taki sam sposób, w jaki vi.mock() mockuje eksporty modułów. Szczegóły patrz automockowanie.

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

Sprawdza, czy dany parametr jest funkcją mockującą. Jeśli używasz TypeScript, zawęzi również jego typ.

vi.clearAllMocks ​

Wywołuje .mockClear() na wszystkich szpiegach. Spowoduje to wyczyszczenie historii mocków bez wpływu na ich implementacje.

vi.resetAllMocks ​

Wywołuje .mockReset() na wszystkich szpiegach. Spowoduje to wyczyszczenie historii mocków i zresetowanie implementacji każdego mocka do oryginalnej.

vi.restoreAllMocks ​

Wywołuje .mockRestore() na wszystkich szpiegach. Spowoduje to wyczyszczenie historii mocków, przywrócenie wszystkich oryginalnych implementacji mocków oraz przywrócenie oryginalnych deskryptorów szpiegowanych obiektów.

vi.spyOn ​

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

Tworzy funkcję szpiegującą (spy) dla metody lub gettera/settera obiektu podobnie do vi.fn(). Zwraca funkcję mockującą.

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

W środowiskach, które obsługują Explicit Resource Management, możesz użyć using zamiast const, aby automatycznie wywołać mockRestore na dowolnej mockowanej funkcji po wyjściu z bloku, w którym się znajduje. Jest to szczególnie przydatne dla szpiegowanych metod:

ts
it('wywołuje console.log', () => {
  using spy = vi.spyOn(console, 'log').mockImplementation(() => {})
  debug('wiadomość')
  expect(spy).toHaveBeenCalled()
})
// console.log jest przywrócone tutaj

TIP

Możesz wywołać vi.restoreAllMocks w afterEach (lub włączyć test.restoreMocks), aby przywrócić wszystkie metody do ich oryginalnych implementacji. Spowoduje to przywrócenie oryginalnego deskryptora obiektu, więc nie będziesz mógł zmienić implementacji metody:

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()); // nadal 42!

TIP

Nie jest możliwe szpiegowanie eksportowanych metod w trybie przeglądarki. Zamiast tego możesz szpiegować każdą eksportowaną metodę, wywołując vi.mock("./file-path.js", { spy: true }). Spowoduje to mockowanie każdego eksportu, ale zachowa jego implementację w nienaruszonym stanie, umożliwiając sprawdzenie, czy metoda została poprawnie wywołana.

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);

I chociaż możliwe jest szpiegowanie eksportów w środowiskach jsdom lub innych środowiskach Node.js, może się to zmienić w przyszłości.

vi.stubEnv ​

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

Zmienia wartość zmiennej środowiskowej w obiektach process.env i import.meta.env. Możesz przywrócić jej wartość, wywołując vi.unstubAllEnvs.

ts
import { vi } from 'vitest';

// `process.env.NODE_ENV` i `import.meta.env.NODE_ENV`
// są "development" przed wywołaniem "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;

// nie zmienia innych zmiennych środowiskowych
import.meta.env.MODE === 'development';

TIP

Możesz również zmienić wartość, po prostu ją przypisując, ale nie będziesz mógł użyć vi.unstubAllEnvs, aby przywrócić poprzednią wartość:

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

vi.unstubAllEnvs ​

  • Typ: () => Vitest

Przywraca wszystkie wartości import.meta.env i process.env, które zostały zmienione za pomocą vi.stubEnv. Gdy zostanie wywołana po raz pierwszy, Vitest zapamiętuje oryginalną wartość i zachowa ją, dopóki unstubAllEnvs nie zostanie wywołane ponownie.

ts
import { vi } from 'vitest';

// `process.env.NODE_ENV` i `import.meta.env.NODE_ENV`
// są "development" przed wywołaniem 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();

// przywraca do wartości, które zostały zapisane przed pierwszym wywołaniem "stubEnv"
process.env.NODE_ENV === 'development';
import.meta.env.NODE_ENV === 'development';

vi.stubGlobal ​

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

Zmienia wartość zmiennej globalnej. Możesz przywrócić jej oryginalną wartość, wywołując vi.unstubAllGlobals.

ts
import { vi } from 'vitest';

// `innerWidth` jest "0" przed wywołaniem stubGlobal

vi.stubGlobal('innerWidth', 100);

innerWidth === 100;
globalThis.innerWidth === 100;
// jeśli używasz jsdom lub happy-dom
window.innerWidth === 100;

TIP

Możesz również zmienić wartość, po prostu przypisując ją do globalThis lub window (jeśli używasz środowiska jsdom lub happy-dom), ale nie będziesz mógł użyć vi.unstubAllGlobals, aby przywrócić oryginalną wartość:

ts
globalThis.innerWidth = 100;
// jeśli używasz jsdom lub happy-dom
window.innerWidth = 100;

vi.unstubAllGlobals ​

  • Typ: () => Vitest

Przywraca wszystkie wartości globalne dla globalThis/global (i window/top/self/parent, jeśli używasz środowiska jsdom lub happy-dom), które zostały zmienione za pomocą vi.stubGlobal. Gdy zostanie wywołana po raz pierwszy, Vitest zapamiętuje oryginalną wartość i zachowa ją, dopóki unstubAllGlobals nie zostanie wywołane ponownie.

ts
import { vi } from 'vitest';

const Mock = vi.fn();

// IntersectionObserver jest "undefined" przed wywołaniem "stubGlobal"

vi.stubGlobal('IntersectionObserver', Mock);

IntersectionObserver === Mock;
global.IntersectionObserver === Mock;
globalThis.IntersectionObserver === Mock;
// jeśli używasz jsdom lub happy-dom
window.IntersectionObserver === Mock;

vi.unstubAllGlobals();

globalThis.IntersectionObserver === undefined;
'IntersectionObserver' in globalThis === false;
// rzuca ReferenceError, ponieważ nie jest zdefiniowane
IntersectionObserver === undefined;

Fałszywe timery ​

Ta sekcja opisuje, jak pracować z fałszywymi timerami.

vi.advanceTimersByTime ​

  • Typ: (ms: number) => Vitest

Ta metoda wywoła każdy zainicjowany timer, aż upłynie określona liczba milisekund lub kolejka będzie pusta - w zależności od tego, co nastąpi wcześniej.

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>

Ta metoda wywoła każdy zainicjowany timer, aż upłynie określona liczba milisekund lub kolejka będzie pusta - w zależności od tego, co nastąpi wcześniej. Będzie to obejmować asynchronicznie ustawione timery.

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

Wywoła następny dostępny timer. Przydatne do wykonywania sprawdzeń między każdym wywołaniem timera. Możesz wywoływać to łańcuchowo, aby samodzielnie zarządzać timerami.

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

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

vi.advanceTimersToNextTimerAsync ​

  • Typ: () => Promise<Vitest>

Wywoła następny dostępny timer i poczeka, aż zostanie rozwiązany, jeśli został ustawiony asynchronicznie. Przydatne do wykonywania sprawdzeń między każdym wywołaniem timera.

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

Podobnie do vi.advanceTimersByTime, ale przesunie timery o milisekundy potrzebne do wykonania wywołań zwrotnych aktualnie zaplanowanych za pomocą requestAnimationFrame.

ts
let frameRendered = false;

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

vi.advanceTimersToNextFrame();

expect(frameRendered).toBe(true);

vi.getTimerCount ​

  • Typ: () => number

Pobiera liczbę oczekujących timerów.

vi.clearAllTimers ​

Usuwa wszystkie timery, które są zaplanowane do uruchomienia. Te timery nigdy nie zostaną uruchomione w przyszłości.

vi.getMockedSystemTime ​

  • Typ: () => Date | null

Zwraca zmockowaną bieżącą datę/czas. Jeśli data nie jest zmockowana, metoda zwróci null.

vi.getRealSystemTime ​

  • Typ: () => number

Podczas używania vi.useFakeTimers wywołania Date.now są mockowane. Jeśli potrzebujesz uzyskać rzeczywisty czas w milisekundach, możesz wykorzystać tę funkcję.

vi.runAllTicks ​

  • Typ: () => Vitest

Wywołuje każde mikrozadanie, które zostało zakolejkowane za pomocą process.nextTick. Spowoduje to również uruchomienie wszystkich mikrozadań zaplanowanych samodzielnie.

vi.runAllTimers ​

  • Typ: () => Vitest

Ta metoda wywoła każdy zainicjowany timer, aż kolejka timerów będzie pusta. Oznacza to, że każdy timer, który zostanie wywołany w trakcie działania runAllTimers, zostanie uruchomiony. Jeśli masz nieskończony interwał, zgłosi błąd po 10 000 prób (można to skonfigurować za pomocą fakeTimers.loopLimit).

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>

Ta metoda asynchronicznie wywoła każdy zainicjowany timer, aż kolejka timerów będzie pusta. Oznacza to, że każdy timer, który zostanie wywołany w trakcie działania runAllTimersAsync, zostanie uruchomiony, nawet asynchroniczne timery. Jeśli masz nieskończony interwał, zgłosi błąd po 10 000 prób (można to skonfigurować za pomocą fakeTimers.loopLimit).

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

await vi.runAllTimersAsync();

// log: result

vi.runOnlyPendingTimers ​

  • Typ: () => Vitest

Ta metoda wywoła każdy timer, który został utworzony po wywołaniu vi.useFakeTimers. Nie uruchomi żadnego timera, który został utworzony podczas jej wywołania.

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

vi.runOnlyPendingTimers();

// log: 1

vi.runOnlyPendingTimersAsync ​

  • Typ: () => Promise<Vitest>

Ta metoda asynchronicznie wywoła każdy timer, który został utworzony po wywołaniu vi.useFakeTimers, nawet asynchroniczne. Nie uruchomi żadnego timera, który został utworzony podczas jej wywołania.

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

Jeśli włączone są fałszywe timery, ta metoda symuluje zmianę zegara systemowego przez użytkownika (będzie miało to wpływ na API związane z datą, takie jak hrtime, performance.now lub new Date()) - jednak nie uruchomi żadnych timerów. Jeśli fałszywe timery nie są włączone, ta metoda będzie mockować tylko wywołania Date.*.

Przydatne, jeśli musisz przetestować coś, co zależy od bieżącej daty - na przykład wywołania Luxon w twoim kodzie.

Akceptuje te same argumenty typu string i number co 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

Aby włączyć mockowanie timerów, musisz wywołać tę metodę. Będzie ona przechwytywać wszystkie dalsze wywołania timerów (takie jak setTimeout, setInterval, clearTimeout, clearInterval, setImmediate, clearImmediate i Date), dopóki nie zostanie wywołane vi.useRealTimers().

Mockowanie nextTick nie jest obsługiwane podczas uruchamiania Vitest w node:child_process z użyciem --pool=forks. NodeJS używa process.nextTick wewnętrznie w node:child_process i zawiesza działanie, gdy jest mockowane. Mockowanie nextTick jest obsługiwane podczas uruchamiania Vitest z --pool=threads.

Implementacja opiera się wewnętrznie na @sinonjs/fake-timers.

TIP

vi.useFakeTimers() nie mockuje automatycznie process.nextTick i queueMicrotask. Możesz to jednak włączyć, określając opcję w argumencie toFake: vi.useFakeTimers({ toFake: ['nextTick', 'queueMicrotask'] }).

vi.isFakeTimers ​

  • Typ: () => boolean

Zwraca true, jeśli włączone są fałszywe timery.

vi.useRealTimers ​

  • Typ: () => Vitest

Gdy timery się wyczerpią, możesz wywołać tę metodę, aby przywrócić mockowane timery do ich oryginalnych implementacji. Wszystkie timery, które zostały zaplanowane wcześniej, zostaną odrzucone.

Różne ​

Zestaw przydatnych funkcji pomocniczych, które udostępnia Vitest.

vi.waitFor ​

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

Czeka na pomyślne wykonanie funkcji zwrotnej. Jeśli funkcja zwrotna zgłosi błąd lub zwróci odrzuconą obietnicę, będzie kontynuować czekanie, aż zakończy się sukcesem lub upłynie limit czasu.

Jeśli opcje są ustawione na liczbę, efekt jest równoważny ustawieniu { timeout: options }.

Jest to bardzo przydatne, gdy trzeba poczekać na zakończenie jakiejś asynchronicznej akcji, na przykład, gdy uruchamiasz serwer i musisz poczekać, aż się uruchomi.

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

test('Serwer uruchomiony pomyślnie', async () => {
  const server = createServer();

  await vi.waitFor(
    () => {
      if (!server.isReady) {
        throw new Error('Serwer nie uruchomiony');
      }

      console.log('Serwer uruchomiony');
    },
    {
      timeout: 500, // domyślnie 1000
      interval: 20, // domyślnie 50
    }
  );
  expect(server.isReady).toBe(true);
});

Działa również dla asynchronicznych wywołań zwrotnych

ts
// @vitest-environment jsdom

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

test('Element istnieje w DOM', async () => {
  // rozpocznij wypełnianie DOM
  populateDOMAsync();

  const element = await vi.waitFor(
    async () => {
      // spróbuj pobrać element, aż będzie istniał
      const element = (await getDOMElementAsync()) as HTMLElement | null;
      expect(element).toBeTruthy();
      expect(element.dataset.initialized).toBeTruthy();
      return element;
    },
    {
      timeout: 500, // domyślnie 1000
      interval: 20, // domyślnie 50
    }
  );
  expect(element).toBeInstanceOf(HTMLElement);
});

Jeśli użyto vi.useFakeTimers, vi.waitFor automatycznie wywołuje vi.advanceTimersByTime(interval) w każdym wywołaniu zwrotnym sprawdzania.

vi.waitUntil ​

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

Jest to podobne do vi.waitFor, ale jeśli funkcja zwrotna zgłosi jakiekolwiek błędy, wykonanie zostanie natychmiast przerwane i pojawi się komunikat o błędzie. Jeśli funkcja zwrotna zwróci wartość falsy, następne sprawdzenie będzie kontynuowane, aż zostanie zwrócona wartość truthy. Jest to przydatne, gdy trzeba poczekać, aż coś będzie istniało, zanim przejdzie się do następnego kroku.

Spójrz na poniższy przykład. Możemy użyć vi.waitUntil, aby poczekać, aż element pojawi się na stronie, a następnie możemy coś z nim zrobić.

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

test('Element renderuje się poprawnie', async () => {
  const element = await vi.waitUntil(() => document.querySelector('.element'), {
    timeout: 500, // domyślnie 1000
    interval: 20, // domyślnie 50
  });

  // zrób coś z elementem
  expect(element.querySelector('.element-child')).toBeTruthy();
});

vi.hoisted ​

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

Wszystkie statyczne instrukcje import w modułach ES są przenoszone na górę pliku, więc każdy kod zdefiniowany przed importami zostanie faktycznie wykonany po wykonaniu importów.

Jednak może być przydatne wykonanie pewnych operacji z efektami ubocznymi, takich jak mockowanie dat przed zaimportowaniem modułu.

Aby ominąć to ograniczenie, możesz przepisać statyczne importy na dynamiczne w ten sposób:

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

Podczas uruchamiania vitest możesz to zrobić automatycznie, używając metody vi.hoisted. Pod maską Vitest przekonwertuje statyczne importy na dynamiczne z zachowaniem dynamicznych powiązań.

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

IMPORTY SĄ NIEDOSTĘPNE

Uruchamianie kodu przed importami oznacza, że nie możesz uzyskać dostępu do zaimportowanych zmiennych, ponieważ nie są jeszcze zdefiniowane:

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

vi.hoisted(() => { value }); // rzuca błąd

Ten kod wygeneruje błąd:

Nie można uzyskać dostępu do '__vi_import_0__' przed inicjalizacją

Jeśli potrzebujesz uzyskać dostęp do zmiennej z innego modułu wewnątrz vi.hoisted, użyj dynamicznego importu:

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

Jednak nie zaleca się importowania czegokolwiek wewnątrz vi.hoisted, ponieważ importy są już przeniesione na górę - jeśli musisz wykonać coś przed uruchomieniem testów, po prostu wykonaj to w samym zaimportowanym module.

Ta metoda zwraca wartość, która została zwrócona z funkcji fabrykującej. Możesz użyć tej wartości w swoich funkcjach fabrykujących vi.mock, jeśli potrzebujesz łatwego dostępu do lokalnie zdefiniowanych zmiennych:

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);

Zauważ, że ta metoda może być również wywoływana asynchronicznie, nawet jeśli twoje środowisko nie obsługuje top-level await:

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

vi.setConfig ​

  • Typ: RuntimeConfig

Aktualizuje konfigurację dla bieżącego pliku testowego. Ta metoda obsługuje tylko opcje konfiguracyjne, które wpłyną na bieżący plik testowy:

ts
vi.setConfig({
  allowOnly: true,
  testTimeout: 10_000,
  hookTimeout: 10_000,
  clearMocks: true,
  restoreMocks: true,
  fakeTimers: {
    now: new Date(2021, 11, 19),
    // obsługuje cały obiekt
  },
  maxConcurrency: 10,
  sequence: {
    hooks: 'stack',
    // obsługuje tylko "sequence.hooks"
  },
});

vi.resetConfig ​

  • Typ: RuntimeConfig

Jeśli vi.setConfig zostało wywołane wcześniej, to zresetuje konfigurację do stanu początkowego.

Pager
Poprzednia stronaFunkcje Mock
Następna stronaexpect

Opublikowano na licencji MIT.

Copyright (c) 2021-Present Vitest Team

https://vitest.dev/api/vi

Opublikowano na licencji MIT.

Copyright (c) 2021-Present Vitest Team