Skip to content
Vitest 1
Main Navigation 指南API配置高級
3.2.0
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();
getApplesSpy.mock.calls.length === 1;

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

getMockImplementation ​

  • 類型: (...args: any) => any

返回目前的模擬實作(如果存在)。

如果模擬是使用 vi.fn 建立的,它會將傳入的方法視為模擬實作。

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

getMockName ​

  • 類型: () => string

返回使用 .mockName(name) 方法賦予模擬的名稱。

mockClear ​

  • 類型: () => MockInstance

清除關於每次呼叫的所有資訊。呼叫後,.mock 上的所有屬性都將返回空狀態。如果您需要在不同的斷言之間清除模擬,這會很有用。

如果您希望在每次測試之前自動呼叫此方法,您可以在配置中啟用 clearMocks 設定。

mockName ​

  • 類型: (name: string) => MockInstance

設定模擬的內部名稱。如果斷言失敗,這有助於識別模擬的名稱。

mockImplementation ​

  • 類型: (fn: Function) => MockInstance

接受一個函數,該函數將用作模擬的實作。

ts
import { vi } from 'vitest';
// ---cut---
const mockFn = vi.fn().mockImplementation(apples => apples + 1);
// or: 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 ​

  • 類型: (fn: Function) => MockInstance

接受一個函數,該函數將在下一次呼叫時用作模擬的實作。可以鏈式呼叫,以便多次函數呼叫產生不同的結果。

ts
import { vi } from 'vitest';
// ---cut---
const myMockFn = vi
  .fn()
  .mockImplementationOnce(() => true)
  .mockImplementationOnce(() => false);

myMockFn(); // true
myMockFn(); // false

當模擬函數用完所有 mockImplementationOnce 設定的實作後,它會調用使用 vi.fn(() => defaultValue) 或 .mockImplementation(() => defaultValue) 設定的預設實作 (如果它們被呼叫):

ts
import { vi } from 'vitest';
// ---cut---
const myMockFn = vi
  .fn(() => 'default')
  .mockImplementationOnce(() => 'first call')
  .mockImplementationOnce(() => 'second call');

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

withImplementation ​

  • 類型: (fn: Function, callback: () => void) => MockInstance
  • 類型: (fn: Function, callback: () => Promise<unknown>) => Promise<MockInstance>

在執行回呼函數時,暫時覆蓋原始模擬實作。

js
import { vi } from 'vitest';
// ---cut---
const myMockFn = vi.fn(() => 'original');

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

myMockFn(); // 'original'

可搭配非同步回呼函數使用。需等待此方法執行完畢,才能恢復使用原始實作。

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

  // We await this call since the callback is async
  await myMockFn.withImplementation(
    () => 'temp',
    async () => {
      myMockFn(); // 'temp'
    }
  );

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

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

mockRejectedValue ​

  • 類型: (value: any) => MockInstance

接受一個值,該值將在呼叫非同步函數時被拒絕 (rejected)。

ts
import { vi } from 'vitest';
// ---cut---
const asyncMock = vi.fn().mockRejectedValue(new Error('Async error'));

await asyncMock(); // throws "Async error"

mockRejectedValueOnce ​

  • 類型: (value: any) => MockInstance

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

ts
import { vi } from 'vitest';
// ---cut---
const asyncMock = vi
  .fn()
  .mockResolvedValueOnce('first call')
  .mockRejectedValueOnce(new Error('Async error'));

await asyncMock(); // first call
await asyncMock(); // throws "Async error"

mockReset ​

  • 類型: () => MockInstance

執行 mockClear 的操作,並將內部實作重置為一個空函數 (呼叫時返回 undefined)。這也會重置所有 "once" 實作。當您想要將模擬完全重置為預設狀態時,這會很有用。

如果您希望在每次測試之前自動呼叫此方法,您可以在配置中啟用 mockReset 設定。

mockRestore ​

  • 類型: () => MockInstance

執行 mockReset 的操作,並將內部實作恢復為原始函數。

請注意,從 vi.fn() 恢復模擬會將實作設定為返回 undefined 的空函數。恢復 vi.fn(impl) 會將實作恢復為 impl。

如果您希望在每次測試之前自動呼叫此方法,您可以在配置中啟用 restoreMocks 設定。

mockResolvedValue ​

  • 類型: (value: any) => MockInstance

接受一個值,該值將在呼叫非同步函數時被解析 (resolved)。

ts
import { vi } from 'vitest';
// ---cut---
const asyncMock = vi.fn().mockResolvedValue(42);

await asyncMock(); // 42

mockResolvedValueOnce ​

  • 類型: (value: any) => MockInstance

接受一個值,該值將在下一次函數呼叫時被解析 (resolved)。如果鏈式呼叫,則每次連續呼叫都會解析指定的值。

ts
import { vi } from 'vitest';
// ---cut---
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 ​

  • 類型: () => MockInstance

如果您需要從方法返回 this 上下文而不調用實際實作,請使用此方法。這是以下程式碼的簡寫:

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

mockReturnValue ​

  • 類型: (value: any) => MockInstance

接受一個值,該值將在每次呼叫模擬函數時傳回。

ts
import { vi } from 'vitest';
// ---cut---
const mock = vi.fn();
mock.mockReturnValue(42);
mock(); // 42
mock.mockReturnValue(43);
mock(); // 43

mockReturnValueOnce ​

  • 類型: (value: any) => MockInstance

接受一個值,該值將在下一次函數呼叫時傳回。如果鏈式呼叫,則每次連續呼叫都會傳回指定的值。

當沒有更多 mockReturnValueOnce 值可供使用時,如果存在先前定義的實作,模擬會回退到該實作。

ts
import { vi } from 'vitest';
// ---cut---
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 ​

此為一個陣列,包含每次呼叫的所有引數。陣列中的每個項目是該呼叫的引數列表。

js
const fn = vi.fn();

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

fn.mock.calls ===
  [
    ['arg1', 'arg2'], // first call
    ['arg3'], // second call
  ];

mock.lastCall ​

這包含上次呼叫的引數。如果未呼叫模擬,則返回 undefined。

mock.results ​

此為一個陣列,包含從函數 returned 的所有值。陣列的一個項目是一個具有 type 和 value 屬性的物件。可用的類型有:

  • 'return' - 函數正常傳回,沒有拋出錯誤。
  • 'throw' - 函數拋出了一個錯誤。

value 屬性包含返回的值或拋出的錯誤。如果函數返回一個 promise,則 value 將是 已解析 的值,而不是實際的 Promise,除非它從未被解析。

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

const result = fn(); // returned 'result'

try {
  fn(); // threw Error
} catch {}

fn.mock.results ===
  [
    // first result
    {
      type: 'return',
      value: 'result',
    },
    // last result
    {
      type: 'throw',
      value: Error,
    },
  ];

mock.invocationCallOrder ​

模擬的執行順序。

這會返回一個數字陣列,這些數字在所有已定義的模擬之間共享。

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

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

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

mock.instances ​

此為一個陣列,包含在使用 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) 2021-Present Vitest Team

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

以 MIT 授權條款 發布。

版權所有 (c) 2021-Present Vitest Team