Skip to content
Vitest 2
Main Navigation 指南API配置瀏覽器模式高級
2.1.9
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

測試 API 參考文件

模擬函數

Vi

expect

expectTypeOf

assert

assertType

本頁導覽

模擬函式 ​

您可以使用 vi.fn 方法建立一個模擬函式來追蹤其執行。如果您想追蹤一個已建立物件上的方法,可以使用 vi.spyOn 方法:

js
import { vi } from 'vitest';

const fn = vi.fn(); // 建立模擬函式
fn('hello world'); // 呼叫模擬函式
fn.mock.calls[0] === ['hello world']; // 檢查第一次呼叫的參數

const market = {
  getApples: () => 100,
};

const getApplesSpy = vi.spyOn(market, 'getApples'); // 監視 market 物件的 getApples 方法
market.getApples(); // 呼叫被監視的方法
getApplesSpy.mock.calls.length === 1; // 檢查被監視的方法是否被呼叫了一次

您應該在 expect 上使用模擬斷言 (mock assertions) (例如,toHaveBeenCalled) 來斷言模擬結果。本 API 參考文件描述了可用的屬性和方法來操作模擬行為。

TIP

下方類型中的自訂函式實作以泛型 <T> 標記。

getMockImplementation ​

ts
function getMockImplementation(): T | undefined;

如果存在,則返回目前的模擬實作。

如果模擬是使用 vi.fn 建立的,它將使用提供的函式作為模擬實作。

如果模擬是使用 vi.spyOn 建立的,除非提供了自訂實作,否則它將返回 undefined。

getMockName ​

ts
function getMockName(): string;

使用它來返回使用 .mockName(name) 方法賦予模擬的名稱。預設情況下,它將返回 vi.fn()。

mockClear ​

ts
function mockClear(): MockInstance<T>;

清除所有關於每次呼叫的資訊。呼叫此方法後,.mock 上的所有屬性將恢復到其初始狀態。此方法不會重設實作。它適用於在不同斷言間清理模擬。

要在每次測試之前自動呼叫此方法,請在設定中啟用 clearMocks 設定。

mockName ​

ts
function mockName(name: string): MockInstance<T>;

設定內部模擬名稱。這對於在斷言失敗時識別模擬很有用。

mockImplementation ​

ts
function mockImplementation(fn: T): MockInstance<T>;

接受一個函式作為模擬實作。TypeScript 期望參數和返回類型與原始函式相符。

ts
const mockFn = vi.fn().mockImplementation((apples: number) => apples + 1);
// 或:vi.fn(apples => apples + 1);

const NelliesBucket = mockFn(0);
const BobsBucket = mockFn(1);

NelliesBucket === 1; // true
BobsBucket === 2; // true

mockFn.mock.calls[0][0] === 0; // true
mockFn.mock.calls[1][0] === 1; // true

mockImplementationOnce ​

ts
function mockImplementationOnce(fn: T): MockInstance<T>;

接受一個函式作為模擬實作。TypeScript 期望參數和返回類型與原始函式相符。此方法可以鏈式呼叫,以針對多次函式呼叫產生不同的結果。

ts
const myMockFn = vi
  .fn()
  .mockImplementationOnce(() => true) // 第一次呼叫
  .mockImplementationOnce(() => false); // 第二次呼叫

myMockFn(); // 第一次呼叫:true
myMockFn(); // 第二次呼叫:false

當模擬函式耗盡實作時,如果呼叫了 vi.fn(() => defaultValue) 或 .mockImplementation(() => defaultValue),它將呼叫預設實作:

ts
const myMockFn = vi
  .fn(() => 'default')
  .mockImplementationOnce(() => 'first call')
  .mockImplementationOnce(() => 'second call');

// 'first call', 'second call', 'default', 'default'
console.log(myMockFn(), myMockFn(), myMockFn(), myMockFn());

withImplementation ​

ts
function withImplementation(fn: T, cb: () => void): MockInstance<T>;
function withImplementation(
  fn: T,
  cb: () => Promise<void>
): Promise<MockInstance<T>>;

在回呼函式執行期間,暫時覆寫原始模擬實作。

js
const myMockFn = vi.fn(() => 'original');

myMockFn.withImplementation(
  () => 'temp',
  () => {
    myMockFn(); // 'temp'
  }
);

myMockFn(); // 'original'

可以與非同步回呼函式一起使用。必須等待此方法執行完畢,才能使用原始實作。

ts
test('async callback', () => {
  const myMockFn = vi.fn(() => 'original');

  // 我們等待此呼叫,因為回呼函式是非同步的
  await myMockFn.withImplementation(
    () => 'temp',
    async () => {
      myMockFn(); // 'temp'
    }
  );

  myMockFn(); // 'original'
});

請注意,此方法優先於 mockImplementationOnce。

mockRejectedValue ​

ts
function mockRejectedValue(value: unknown): MockInstance<T>;

接受一個錯誤,當非同步函式被呼叫時將被拒絕。

ts
const asyncMock = vi.fn().mockRejectedValue(new Error('Async error'));

await asyncMock(); // 拋出 Error('Async error')

mockRejectedValueOnce ​

ts
function mockRejectedValueOnce(value: unknown): MockInstance<T>;

接受一個值,該值將在下一次呼叫函式時被拒絕。如果鏈式呼叫,每次連續呼叫都將拒絕指定的值。

ts
const asyncMock = vi
  .fn()
  .mockResolvedValueOnce('first call')
  .mockRejectedValueOnce(new Error('Async error'));

await asyncMock(); // 'first call'
await asyncMock(); // 拋出 Error('Async error')

mockReset ​

ts
function mockReset(): MockInstance<T>;

執行與 mockClear 相同的操作,並將內部實作設定為一個空函式(呼叫時會回傳 undefined)。這也會重設所有「一次性」實作。它對於將模擬完全重設為其預設狀態很有用。

要在每次測試之前自動呼叫此方法,請在設定中啟用 mockReset 設定。

mockRestore ​

ts
function mockRestore(): MockInstance<T>;

執行與 mockReset 相同的操作,並將內部實作恢復為原始函式。

請注意,恢復使用 vi.fn() 建立的模擬,會將實作設定為一個回傳 undefined 的空函式。恢復使用 vi.fn(impl) 建立的模擬,會將實作恢復為 impl。

要在每次測試之前自動呼叫此方法,請在設定中啟用 restoreMocks 設定。

mockResolvedValue ​

ts
function mockResolvedValue(value: Awaited<ReturnType<T>>): MockInstance<T>;

接受一個值,當非同步函式被呼叫時將被解析。TypeScript 只會接受與原始函式返回類型相符的值。

ts
const asyncMock = vi.fn().mockResolvedValue(42);

await asyncMock(); // 42

mockResolvedValueOnce ​

ts
function mockResolvedValueOnce(value: Awaited<ReturnType<T>>): MockInstance<T>;

接受一個值,該值將在下一次呼叫函式時被解析。TypeScript 只會接受與原始函式返回類型相符的值。如果鏈式呼叫,每次連續呼叫都將解析指定的值。

ts
const asyncMock = vi
  .fn()
  .mockResolvedValue('default')
  .mockResolvedValueOnce('first call')
  .mockResolvedValueOnce('second call');

await asyncMock(); // first call
await asyncMock(); // second call
await asyncMock(); // default
await asyncMock(); // default

mockReturnThis ​

ts
function mockReturnThis(): MockInstance<T>;

如果您需要在不呼叫實際實作的情況下從方法返回 this 上下文,請使用此方法。此為以下程式碼的簡寫形式:

ts
spy.mockImplementation(function () {
  return this;
});

mockReturnValue ​

ts
function mockReturnValue(value: ReturnType<T>): MockInstance<T>;

接受一個值,該值將在每次呼叫模擬函式時回傳。TypeScript 只會接受與原始函式返回類型相符的值。

ts
const mock = vi.fn();
mock.mockReturnValue(42);
mock(); // 42
mock.mockReturnValue(43);
mock(); // 43

mockReturnValueOnce ​

ts
function mockReturnValueOnce(value: ReturnType<T>): MockInstance<T>;

接受一個值,該值將在每次呼叫模擬函式時回傳。TypeScript 只會接受與原始函式返回類型相符的值。

當模擬函式耗盡實作時,如果呼叫了 vi.fn(() => defaultValue) 或 .mockImplementation(() => defaultValue),它將呼叫預設實作:

ts
const myMockFn = vi
  .fn()
  .mockReturnValue('default')
  .mockReturnValueOnce('first call')
  .mockReturnValueOnce('second call');

// 'first call', 'second call', 'default', 'default'
console.log(myMockFn(), myMockFn(), myMockFn(), myMockFn());

mock.calls ​

ts
const calls: Parameters<T>[];

這是一個陣列,包含每次呼叫的所有參數。陣列中的每個項目都是該次呼叫的參數。

js
const fn = vi.fn();

fn('arg1', 'arg2');
fn('arg3');

fn.mock.calls ===
  [
    ['arg1', 'arg2'], // 第一次呼叫
    ['arg3'], // 第二次呼叫
  ];

mock.lastCall ​

ts
const lastCall: Parameters<T> | undefined;

這包含最後一次呼叫的參數。如果模擬未被呼叫,則會回傳 undefined。

mock.results ​

ts
interface MockResultReturn<T> {
  type: 'return';
  /**
   * 從函式回傳的值。
   * 如果函式回傳 Promise,則這將是解析後的值。
   */
  value: T;
}

interface MockResultIncomplete {
  type: 'incomplete';
  value: undefined;
}

interface MockResultThrow {
  type: 'throw';
  /**
   * 在函式執行期間拋出的錯誤。
   */
  value: any;
}

type MockResult<T> =
  | MockResultReturn<T>
  | MockResultThrow
  | MockResultIncomplete;

const results: MockResult<ReturnType<T>>[];

這是一個陣列,包含從函式 回傳 的所有值。陣列中的每個項目都是一個具有 type 和 value 屬性的物件。可用的類型有:

  • 'return' - 函式返回而未拋出錯誤。
  • 'throw' - 函式拋出值。

value 屬性包含回傳的值或拋出的錯誤。如果函式回傳了一個 Promise,即使 Promise 被拒絕,result 的 type 也將始終是 'return'。

js
const fn = vi
  .fn()
  .mockReturnValueOnce('result')
  .mockImplementationOnce(() => {
    throw new Error('thrown error');
  });

const result = fn(); // 回傳 'result'

try {
  fn(); // 拋出 Error
} catch {}

fn.mock.results ===
  [
    // 第一個結果
    {
      type: 'return',
      value: 'result',
    },
    // 最後一個結果
    {
      type: 'throw',
      value: Error,
    },
  ];

mock.settledResults ​

ts
interface MockSettledResultFulfilled<T> {
  type: 'fulfilled';
  value: T;
}

interface MockSettledResultRejected {
  type: 'rejected';
  value: any;
}

export type MockSettledResult<T> =
  | MockSettledResultFulfilled<T>
  | MockSettledResultRejected;

const settledResults: MockSettledResult<Awaited<ReturnType<T>>>[];

一個陣列,包含從函式 解析 或 拒絕 的所有值。

如果函式從未解析或拒絕,此陣列將為空。

js
const fn = vi.fn().mockResolvedValueOnce('result');

const result = fn();

fn.mock.settledResults === [];

await result;

fn.mock.settledResults ===
  [
    {
      type: 'fulfilled',
      value: 'result',
    },
  ];

mock.invocationCallOrder ​

ts
const invocationCallOrder: number[];

此屬性回傳模擬函式的執行順序。它是一個數字陣列,在所有已定義的模擬之間共享。

js
const fn1 = vi.fn();
const fn2 = vi.fn();

fn1();
fn2();
fn1();

fn1.mock.invocationCallOrder === [1, 3];
fn2.mock.invocationCallOrder === [2];

mock.contexts ​

ts
const contexts: ThisParameterType<T>[];

此屬性是一個陣列,包含每次呼叫模擬函式時使用的 this 值。

js
const fn = vi.fn();
const context = {};

fn.apply(context);
fn.call(context);

fn.mock.contexts[0] === context;
fn.mock.contexts[1] === context;

mock.instances ​

ts
const instances: ReturnType<T>[];

此屬性是一個陣列,包含當使用 new 關鍵字呼叫模擬時建立的所有實例。請注意,這是函式的實際上下文 (this),而不是回傳值。

WARNING

如果模擬是使用 new MyClass() 實例化的,則 mock.instances 將是一個包含一個值的陣列:

js
const MyClass = vi.fn();
const a = new MyClass();

MyClass.mock.instances[0] === a;

如果您從建構函式回傳一個值,它將不會在 instances 陣列中,而是在 results 中:

js
const Spy = vi.fn(() => ({ method: vi.fn() }));
const a = new Spy();

Spy.mock.instances[0] !== a;
Spy.mock.results[0] === a;
Pager
上一頁測試 API 參考文件
下一頁Vi

以 MIT 授權條款 發布。

版權所有 (c) 2024 Mithril Contributors

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

以 MIT 授權條款 發布。

版權所有 (c) 2024 Mithril Contributors