Skip to content
Vitest 0
Main Navigation 指南API配置高級
1.6.1
0.34.6

繁體中文

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

繁體中文

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

外觀

Sidebar Navigation

指南

為什麼使用 Vitest

開始使用

功能特性

工作區

命令列界面

測試過濾器

覆蓋率

快照

模擬(Mocking)

型別測試

Vitest UI

瀏覽器模式 (實驗性)

原始碼測試

測試上下文

測試環境

擴展匹配器

IDE 整合支援

偵錯

與其他測試執行器的比較

遷移指南

常見錯誤

API

測試 API 參考文件

模擬函數 (Mock Functions)

Vi

expect

expectTypeOf

assertType

配置

配置 Vitest

本頁導覽

Vi ​

Vitest 透過其 vi 輔助工具提供實用工具函式來協助您。您可以全域使用它(當 全域配置 被啟用時),或從 vitest 匯入:

js
import { vi } from 'vitest';

vi.advanceTimersByTime ​

  • 類型: (ms: number) => Vitest

    作用類似於 runAllTimers,但會將時間推進指定的毫秒數。例如,以下程式碼會記錄 1, 2, 3,且不會拋出錯誤:

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

vi.advanceTimersByTimeAsync ​

  • 類型: (ms: number) => Promise<Vitest>

    作用類似於 runAllTimersAsync,但會將時間推進指定的毫秒數。這將包括以非同步方式設定的計時器。例如,以下程式碼會記錄 1, 2, 3,且不會拋出錯誤:

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

vi.advanceTimersToNextTimer ​

  • 類型: () => Vitest

    會呼叫下一個可用的計時器。適用於在每次計時器呼叫後進行斷言。您可以鏈式呼叫它來自行管理計時器。

    ts
    let i = 0;
    setInterval(() => console.log(++i), 50);
    
    vi.advanceTimersToNextTimer() // 記錄 1
      .advanceTimersToNextTimer() // 記錄 2
      .advanceTimersToNextTimer(); // 記錄 3

vi.advanceTimersToNextTimerAsync ​

  • 類型: () => Promise<Vitest>

    即使是以非同步方式設定的計時器,也會呼叫下一個可用的計時器。適用於在每次計時器呼叫後進行斷言。您可以鏈式呼叫它來自行管理計時器。

    ts
    let i = 0;
    setInterval(() => Promise.resolve().then(() => console.log(++i)), 50);
    
    vi.advanceTimersToNextTimerAsync() // 記錄 1
      .advanceTimersToNextTimerAsync() // 記錄 2
      .advanceTimersToNextTimerAsync(); // 記錄 3

vi.getTimerCount ​

  • 類型: () => number

    取得等待中的計時器數量。

vi.clearAllMocks ​

將會對所有間諜函式呼叫 .mockClear() 方法。這將清除 mock 歷史記錄,但不會將其實現重設為預設值。

vi.clearAllTimers ​

移除所有已排程執行的計時器。這些計時器將永遠不會在未來執行。

vi.dynamicImportSettled ​

如果您有一個同步呼叫啟動了模組的匯入,且您需要等待該匯入完成,這會很有用。

vi.fn ​

  • 類型: (fn?: Function) => Mock

    建立一個函式的間諜函式 (spy),即使不使用函式也能初始化。每次呼叫函式時,它都會儲存其呼叫參數、回傳值和實例。此外,您可以使用 方法 來操作其行為。 如果沒有提供函式,mock 將在呼叫時傳回 undefined。

    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.getMockedSystemTime ​

  • 類型: () => Date | null

    傳回使用 setSystemTime 設定的模擬當前日期。如果日期未被 mock,將傳回 null。

vi.getRealSystemTime ​

  • 類型: () => number

    當使用 vi.useFakeTimers 時,Date.now 的呼叫會被 mock。如果您需要取得以毫秒為單位的實際時間,您可以呼叫此函式。

vi.hoisted ​

  • 類型: <T>(factory: () => T) => T

  • 版本: 自 Vitest 0.31.0 起

    ES 模組中的所有靜態 import 語句都會被置頂到檔案的最上方,因此在匯入之前定義的任何程式碼實際上會在評估匯入之後執行。

    然而,在匯入模組之前執行一些副作用,例如模擬日期,可能會很有用。

    為了繞過這個限制,您可以將靜態匯入重寫為動態匯入,如下所示:

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

    當執行 vitest 時,您可以使用 vi.hoisted 方法自動執行此操作。

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

    此方法傳回從 factory 傳回的值。如果需要輕鬆存取本機定義的變數,您可以在 vi.mock 的 factory 中使用該值:

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

vi.mock ​

  • 類型: (path: string, factory?: () => unknown) => void

    將從提供的 path 匯入的所有模組替換為另一個模組。您可以在路徑中使用已配置的 Vite 別名。對 vi.mock 的呼叫會被提升 (hoisted),因此呼叫它的位置並不重要。它將始終在所有匯入之前執行。如果您需要引用其範圍之外的一些變數,您可以在 vi.hoisted 中定義它們,並在 vi.mock 中引用它們。

    WARNING

    vi.mock 僅適用於使用 import 關鍵字匯入的模組。它不適用於 require。

    Vitest 靜態分析您的檔案以提升 vi.mock。這表示您不能使用未直接從 vitest 套件匯入的 vi (例如,從其他工具函式檔案匯入)。要解決此問題,請始終使用從 vitest 匯入的 vi 使用 vi.mock,或啟用 globals 配置選項。

    WARNING

    目前在 瀏覽器模式 中不支援模組的 Mock。您可以在 GitHub issue 中追蹤此功能。

    如果定義了 factory,則所有匯入都將傳回其結果。Vitest 僅呼叫 factory 一次,並快取結果以供所有後續匯入使用,直到呼叫 vi.unmock 或 vi.doUnmock。

    與 jest 不同,factory 可以是非同步的,因此您可以使用 vi.importActual 或在其中接收到的 helper 作為第一個引數,以取得原始模組。

    ts
    vi.mock('./path/to/module.js', async importOriginal => {
      const mod = await importOriginal();
      return {
        ...mod,
        // 取代一些 exports
        namedExport: vi.fn(),
      };
    });

    WARNING

    vi.mock 會被提升(換句話說,移動)到檔案的頂部。這表示無論您在哪裡編寫它(無論是在 beforeEach 還是 test 中),它實際上都會在那之前被呼叫。

    這也表示您不能在 factory 中使用在 factory 外部定義的任何變數。

    如果您需要在 factory 中使用變數,請嘗試 vi.doMock。它的工作方式相同,但不會被提升。請注意,它只會 mock 後續的匯入。

    如果 vi.hoisted 方法在 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

    如果您要模擬 (mock) 具有預設匯出的模組,您需要在回傳的 factory 函式物件中提供一個 default 鍵。這是一個 ES 模組特有的特殊情況,因此 jest 文件可能會有所不同,因為 jest 使用 CommonJS 模組。例如,

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

    如果有一個 __mocks__ 資料夾與您要 mock 的檔案並排,並且未提供 factory,Vitest 將嘗試在 __mocks__ 子資料夾中找到具有相同名稱的檔案,並將其用作實際模組。如果您要 mock 依賴項,Vitest 將嘗試在專案的 root 中找到一個 __mocks__ 資料夾(預設為 process.cwd())。您可以透過 deps.moduleDirectories 配置選項告訴 Vitest 依賴項的位置。

    例如,您有以下檔案結構:

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

    如果您在測試檔案中呼叫 vi.mock 而未提供 factory,它將在 __mocks__ 資料夾中找到一個檔案以用作模組:

    ts
    // increment.test.js
    import { vi } from 'vitest';
    
    // axios 是來自 `__mocks__/axios.js` 的預設匯出
    import axios from 'axios';
    
    // increment 是來自 `src/__mocks__/increment.js` 的具名匯出
    import { increment } from '../increment.js';
    
    vi.mock('axios');
    vi.mock('../increment.js');
    
    axios.get(`/apples/${increment(1)}`);

    WARNING

    請注意,如果您不呼叫 vi.mock,則模組不會自動 mock。要模仿 Jest 的自動 mock 行為,您可以為 setupFiles 中的每個所需模組呼叫 vi.mock。

    如果沒有 __mocks__ 資料夾或提供 factory,Vitest 將匯入原始模組並自動 mock 其所有匯出。有關套用的規則,請參閱 演算法。

vi.doMock ​

  • 類型: (path: string, factory?: () => unknown) => void

    與 vi.mock 相同,但它不會被提升到檔案的頂部,因此您可以參考全域檔案範圍中的變數。模組的下一個 動態匯入 將被 mock。這不會 mock 在呼叫此函式之前匯入的模組。

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

// 模組未被 mock,因為 vi.doMock 尚未被呼叫
increment(1) === 2;

let mockedIncrement = 100;

beforeEach(() => {
  // 您可以存取 factory 內的變數
  vi.doMock('./increment.js', () => ({ increment: () => ++mockedIncrement }));
});

test('匯入的下一個模組會是模擬 (mock) 的模組', async () => {
  // 原始匯入未被 MOCK,因為 vi.doMock 是在匯入後評估的
  expect(increment(1)).toBe(2);
  const { increment: mockedIncrement } = await import('./increment.js');
  // 新的動態匯入傳回 mock 的模組
  expect(mockedIncrement(1)).toBe(101);
  expect(mockedIncrement(1)).toBe(102);
  expect(mockedIncrement(1)).toBe(103);
});

vi.mocked ​

  • 類型: <T>(obj: T, deep?: boolean) => MaybeMockedDeep<T>

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

    這是 TypeScript 的類型輔助函式,實際上只會回傳傳入的物件。

    當 partial 為 true 時,它將期望 Partial<T> 作為傳回值。

    ts
    import example from './example.js';
    
    vi.mock('./example.js');
    
    test('1+1 等於 2', async () => {
      vi.mocked(example.calc).mockRestore();
    
      const res = example.calc(1, '+', 1);
    
      expect(res).toBe(2);
    });

vi.importActual ​

  • 類型: <T>(path: string) => Promise<T>

    匯入模組,繞過所有是否該被模擬的檢查。如果您想部分 mock 模組,這會很有用。

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

vi.importMock ​

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

    匯入一個模組,其中所有屬性(包括巢狀屬性)都被 mock。遵循與 vi.mock 相同的規則。有關套用的規則,請參閱 演算法。

vi.resetAllMocks ​

將在所有 spies 上呼叫 .mockReset() 方法。這將清除 mock 歷史記錄並將其實現重設為空函式(將傳回 undefined)。

vi.resetConfig ​

  • 類型: RuntimeConfig

    如果之前呼叫了 vi.setConfig,這將重設配置為原始狀態。

vi.resetModules ​

  • 類型: () => Vitest

    透過清除所有模組的快取來重設模組註冊表。這允許在重新匯入時重新評估模組。最上層的匯入無法重新評估。這對於隔離測試之間本機狀態發生衝突的模組非常有用。

    ts
    import { vi } from 'vitest';
    
    import { data } from './data.js'; // 將不會在每個測試之前重新評估
    
    beforeEach(() => {
      vi.resetModules();
    });
    
    test('變更狀態', async () => {
      const mod = await import('./some/path.js'); // 將會被重新評估
      mod.changeLocalState('new value');
      expect(mod.getLocalState()).toBe('new value');
    });
    
    test('模組具有舊狀態', async () => {
      const mod = await import('./some/path.js'); // 將會被重新評估
      expect(mod.getLocalState()).toBe('old value');
    });

WARNING

不會重設 mocks 註冊表。要清除 mocks 註冊表,請使用 vi.unmock 或 vi.doUnmock。

vi.restoreAllMocks ​

將在所有 spies 上呼叫 .mockRestore() 方法。這將清除 mock 歷史記錄並將其實現重設為原始狀態。

vi.stubEnv ​

  • 類型: (name: string, value: string) => Vitest

  • 版本: 自 Vitest 0.26.0 起

    變更環境變數在 process.env 和 import.meta.env 中的值。您可以透過呼叫 vi.unstubAllEnvs 來還原其值。

ts
import { vi } from 'vitest';

// 在呼叫 `vi.stubEnv` 之前,`process.env.NODE_ENV` 和 `import.meta.env.NODE_ENV`
// 是 "development"

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

process.env.NODE_ENV === 'production';
import.meta.env.NODE_ENV === 'production';
// 不會變更其他環境變數
import.meta.env.MODE === 'development';

TIP

您也可以透過簡單地指派值來變更該值,但是您將無法使用 vi.unstubAllEnvs 來還原先前的值:

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

vi.unstubAllEnvs ​

  • 類型: () => Vitest

  • 版本: 自 Vitest 0.26.0 起

    還原所有透過 vi.stubEnv 變更的 import.meta.env 和 process.env 值。 第一次呼叫時,Vitest 會記住原始值並儲存,直到再次呼叫 vi.unstubAllEnvs。

ts
import { vi } from 'vitest';

// `process.env.NODE_ENV` 和 `import.meta.env.NODE_ENV`
// 在呼叫 stubEnv 之前是 "development"

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

// 還原為第一次呼叫 "stubEnv" 之前儲存的值
process.env.NODE_ENV === 'development';
import.meta.env.NODE_ENV === 'development';

vi.stubGlobal ​

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

    變更全域變數的值。 您可以透過呼叫 vi.unstubAllGlobals 來恢復其原始值。

ts
import { vi } from 'vitest';

// 在調用 stubGlobal 之前,`innerWidth` 為 "0"

vi.stubGlobal('innerWidth', 100);

innerWidth === 100;
globalThis.innerWidth === 100;
// 如果您使用 jsdom 或 happy-dom
window.innerWidth === 100;

TIP

您也可以簡單地將值賦予 globalThis 或 window(如果您使用 jsdom 或 happy-dom 環境)來變更值,但您將無法使用 vi.unstubAllGlobals 來恢復原始值:

ts
globalThis.innerWidth = 100;
// 如果您使用 jsdom 或 happy-dom
window.innerWidth = 100;

vi.unstubAllGlobals ​

  • 類型: () => Vitest

  • 版本: 自 Vitest 0.26.0 起

    還原 globalThis/global (以及如果您使用 jsdom 或 happy-dom 環境,則還原 window/top/self/parent) 上所有使用 vi.stubGlobal 變更的全域值。 第一次呼叫時,Vitest 會記住原始值並儲存,直到再次呼叫 vi.unstubAllGlobals。

ts
import { vi } from 'vitest';

const Mock = vi.fn();

// 在呼叫 "stubGlobal" 之前,IntersectionObserver 為 "undefined"

vi.stubGlobal('IntersectionObserver', Mock);

IntersectionObserver === Mock;
global.IntersectionObserver === Mock;
globalThis.IntersectionObserver === Mock;
// 如果您使用 jsdom 或 happy-dom
window.IntersectionObserver === Mock;

vi.unstubAllGlobals();

globalThis.IntersectionObserver === undefined;
'IntersectionObserver' in globalThis === false;
// 拋出 ReferenceError,因為未定義
IntersectionObserver === undefined;

vi.runAllTicks ​

  • 類型: () => Vitest

    呼叫 process.nextTick 排隊的每個微任務。 這也會執行所有由它們自己排程的微任務。

vi.runAllTimers ​

  • 類型: () => Vitest

    此方法會調用每個已啟動的計時器,直到計時器佇列為空。 這表示在 runAllTimers 執行期間呼叫的每個計時器都會被觸發。 如果有無限間隔,則會在嘗試 10,000 次後拋出錯誤。 例如,這將記錄 1, 2, 3:

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

vi.runAllTimersAsync ​

  • 類型: () => Promise<Vitest>

    此方法會非同步地調用每個已啟動的計時器,直到計時器佇列為空。 這表示在 runAllTimersAsync 執行期間呼叫的每個計時器都會被觸發,即使是異步計時器。 如果有無限間隔,則會在嘗試 10,000 次後拋出錯誤。 例如,這將記錄 result:

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

vi.runOnlyPendingTimers ​

  • 類型: () => Vitest

    此方法會呼叫在 vi.useFakeTimers() 呼叫後啟動的每個計時器。 它不會觸發在該方法呼叫期間啟動的任何計時器。 例如,這只會記錄 1:

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

vi.runOnlyPendingTimersAsync ​

  • 類型: () => Promise<Vitest>

    此方法會非同步地呼叫在 vi.useFakeTimers() 呼叫後啟動的每個計時器,即使是異步計時器。 它不會觸發在該方法呼叫期間啟動的任何計時器。 例如,這會記錄 2, 3, 3, 1:

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

vi.setSystemTime ​

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

    將目前日期設定為傳入的日期。 之後所有 Date 呼叫都會傳回此日期。

    如果您需要測試任何依賴目前日期的內容(例如,程式碼中的 luxon 呼叫),這非常有用。

    ts
    const date = new Date(1998, 11, 19);
    
    vi.useFakeTimers();
    vi.setSystemTime(date);
    
    expect(Date.now()).toBe(date.valueOf());
    
    vi.useRealTimers();

vi.setConfig ​

  • 類型: RuntimeConfig

    更新目前測試檔案的配置。 您只能影響執行測試時使用的值。

vi.spyOn ​

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

    在物件的方法或 getter/setter 上建立一個間諜 (spy)。

    ts
    let apples = 0;
    const cart = {
      getApples: () => 13,
    };
    
    const spy = vi.spyOn(cart, 'getApples').mockImplementation(() => apples);
    apples = 1;
    
    expect(cart.getApples()).toBe(1);
    
    expect(spy).toHaveBeenCalled();
    expect(spy).toHaveReturnedWith(1);

vi.stubGlobal ​

  • 類型: (key: keyof globalThis & Window, value: any) => Vitest

    將一個值設定到全域變數上。 如果您使用 jsdom 或 happy-dom,也會將該值設定到 window 物件上。

    在 「模擬全域變數」章節 中閱讀更多內容。

vi.unmock ​

  • 類型: (path: string) => void

    從模擬登錄檔中移除模組。 所有匯入呼叫都會傳回原始模組,即使該模組之前已被模擬。 此呼叫會被提升(移動)到檔案的頂部,因此只會取消模擬在 setupFiles 中定義的模組,例如。

vi.doUnmock ​

  • 類型: (path: string) => void

    與 vi.unmock 相同,但不會提升到檔案的頂部。 模組的下一次匯入會匯入原始模組,而不是模擬模組。 這不會取消模擬先前已匯入的模組。

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

// increment 已經被模擬,因為 vi.mock 被提升
increment(1) === 100;

// 這被提升,並且在第 1 行的匯入之前呼叫 factory
vi.mock('./increment.js', () => ({ increment: () => 100 }));

// 所有呼叫都被模擬,並且 `increment` 總是返回 100
increment(1) === 100;
increment(30) === 100;

// 這沒有被提升,因此其他匯入將返回未模擬的模組
vi.doUnmock('./increment.js');

// 這仍然返回 100,因為 `vi.doUnmock` 不會重新評估模組
increment(1) === 100;
increment(30) === 100;

// 下一個匯入未被模擬,現在 `increment` 是返回 count + 1 的原始函式
const { increment: unmockedIncrement } = await import('./increment.js');

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

vi.useFakeTimers ​

  • 類型: () => Vitest

    若要啟用模擬計時器,您需要呼叫此方法。此方法會包裝所有後續對計時器的呼叫 (例如 setTimeout、setInterval、clearTimeout、clearInterval、nextTick、setImmediate、clearImmediate 和 Date),直到呼叫 vi.useRealTimers() 為止。

    當使用 --no-threads 在 node:child_process 內部執行 Vitest 時,不支援模擬 nextTick。 NodeJS 在 node:child_process 內部使用 process.nextTick,並且在被模擬時會掛起。 當使用 --threads 執行 Vitest 時,支援模擬 nextTick。

    該實作在內部基於 @sinonjs/fake-timers。

    TIP

    自版本 0.35.0 起,vi.useFakeTimers() 不再自動模擬 process.nextTick。 仍然可以透過在 toFake 參數中指定選項來模擬它:vi.useFakeTimers({ toFake: ['nextTick'] })。

vi.isFakeTimers ​

  • 類型: () => boolean

  • 版本: 自 Vitest 0.34.5 起

    如果已啟用模擬計時器,則返回 true。

vi.useRealTimers ​

  • 類型: () => Vitest

    當計時器測試完成時,您可以呼叫此方法,將模擬計時器恢復為其原始實作。之前執行的所有計時器都不會被還原。

vi.waitFor ​

  • 類型: <T>(callback: WaitForCallback<T>, options?: number | WaitForOptions) => Promise<T>
  • 版本: 自 Vitest 0.34.5 起

等待回呼成功執行。 如果回呼拋出錯誤或返回 rejected promise,則會持續等待,直到成功或逾時。

當您需要等待某些異步動作完成時,這非常有用,例如,當您啟動伺服器並需要等待它啟動時。

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, // 預設為 1000
      interval: 20, // 預設為 50
    }
  );
  expect(server.isReady).toBe(true);
});

它也適用於異步回呼

ts
// @vitest-environment jsdom

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

test('Element exists in a DOM', async () => {
  // 開始填充 DOM
  populateDOMAsync();

  const element = await vi.waitFor(
    async () => {
      // 嘗試獲取元素,直到它存在
      const element = (await getDOMElementAsync()) as HTMLElement | null;
      expect(element).toBeTruthy();
      expect(element.dataset.initialized).toBeTruthy();
      return element;
    },
    {
      timeout: 500, // 預設為 1000
      interval: 20, // 預設為 50
    }
  );
  expect(element).toBeInstanceOf(HTMLElement);
});

如果使用 vi.useFakeTimers,vi.waitFor 會在每次檢查回呼中自動呼叫 vi.advanceTimersByTime(interval)。

vi.waitUntil ​

  • 類型: <T>(callback: WaitUntilCallback<T>, options?: number | WaitUntilOptions) => Promise<T>
  • 版本: 自 Vitest 0.34.5 起

這與 vi.waitFor 相似,但如果回呼拋出任何錯誤,執行會立即中斷並收到錯誤訊息。 如果回呼返回 falsy 值,則會繼續進行下一個檢查,直到返回 truthy 值為止。 當您需要等待某個東西存在才能執行下一步時,這會非常有用。

請看下面的示例。 我們可以使用 vi.waitUntil 等待元素出現在頁面上,然後我們可以對該元素進行操作。

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

test('Element render correctly', async () => {
  const element = await vi.waitUntil(() => document.querySelector('.element'), {
    timeout: 500, // 預設為 1000
    interval: 20, // 預設為 50
  });

  // 對該元素進行操作
  expect(element.querySelector('.element-child')).toBeTruthy();
});
Pager
上一頁模擬函數 (Mock Functions)
下一頁expect

以 MIT 授權條款 發布。

版權所有 (c) 2024 Mithril Contributors

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

以 MIT 授權條款 發布。

版權所有 (c) 2024 Mithril Contributors