跳到內容

Vi

Vitest 提供工具函式,透過其 vi 輔助程式協助您。您可以在全域存取它(當 全域設定 已啟用時),或直接從 vitest 匯入它

js
import { vi } from 'vitest'

模擬模組

本節說明當 模擬模組 時,您可以使用的 API。請注意,Vitest 不支援模擬使用 require() 匯入的模組。

vi.mock

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

用另一個模組取代從提供的 path 匯入的所有模組。您可以在路徑中使用已設定的 Vite 別名。對 vi.mock 的呼叫會被提升,因此您在哪裡呼叫它並不重要。它將永遠在所有匯入之前執行。如果您需要參照其範圍之外的一些變數,您可以在 vi.hoisted 內定義它們,並在 vi.mock 內參照它們。

警告

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

為了提升 vi.mock,Vitest 會靜態分析您的檔案。它表示從 vitest 套件中未直接匯入的 vi(例如,從某些公用程式檔案中)無法使用。使用從 vitest 匯入的 vi 來使用 vi.mock,或啟用 globals 設定選項。

Vitest 不會模擬在 設定檔 中匯入的模組,因為它們在測試檔執行時已被快取。您可以在 vi.hoisted 中呼叫 vi.resetModules(),以在執行測試檔之前清除所有模組快取。

警告

瀏覽器模式 目前不支援模擬模組。您可以在 GitHub 議題 中追蹤此功能。

如果定義了 factory,所有匯入都將傳回其結果。Vitest 只呼叫一次工廠,並將結果快取,供所有後續匯入使用,直到呼叫 vi.unmockvi.doUnmock 為止。

jest 不同,工廠可以是非同步的。您可以使用 vi.importActual 或一個輔助函式,並將工廠作為第一個引數傳入,並在其中取得原始模組。

js
// when using JavaScript

.('./path/to/module.js', async () => {
  const  = await ()
  return {
    ...,
    // replace some exports
    : .(),
  }
})
ts
// when using TypeScript

vi.mock('./path/to/module.js', async (importOriginal) => {
  const mod = await importOriginal<typeof import('./path/to/module.js')>()
  return {
    ...mod,
    // replace some exports
    namedExport: vi.fn(),
  }
})

警告

vi.mock 會被提升(換句話說,移至檔案頂端。這表示無論您在哪裡撰寫它(無論是在 beforeEachtest 中),它實際上都會在之前被呼叫。

這也表示您無法在工廠中使用任何在工廠外部定義的變數。

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

如果您在 vi.mock 之前宣告了 vi.hoisted 方法定義的變數,您也可以參照它們。

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)

警告

如果您要模擬具有預設匯出的模組,您需要在傳回的工廠函式物件中提供一個 default 鍵。這是 ES 模組特有的注意事項;因此,jest 文件可能有所不同,因為 jest 使用 CommonJS 模組。例如,

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

如果在您要模擬的檔案旁邊有一個 __mocks__ 資料夾,並且未提供工廠,Vitest 會嘗試在 __mocks__ 子資料夾中找到具有相同名稱的檔案,並將其用作實際模組。如果您要模擬相依項,Vitest 會嘗試在專案的 根目錄(預設為 process.cwd())中找到 __mocks__ 資料夾。您可以透過 deps.moduleDirectories 設定選項告訴 Vitest 相依項位於何處。

例如,您有這個檔案結構

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

如果您在測試檔案中呼叫 vi.mock 而未提供工廠,它會在 __mocks__ 資料夾中尋找檔案,並將其用作模組

ts
// increment.test.js
import { vi } from 'vitest'

// axios is a default export from `__mocks__/axios.js`
import axios from 'axios'

// increment is a named export from `src/__mocks__/increment.js`
import { increment } from '../increment.js'

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

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

警告

請注意,如果您未呼叫 vi.mock,模組不會自動進行模擬。若要複製 Jest 的自動模擬行為,您可以在 setupFiles 中為每個必要的模組呼叫 vi.mock

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

vi.doMock

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

vi.mock 相同,但它不會提升到檔案頂端,因此您可以參照全域檔案範圍內的變數。模組的下次 動態匯入 將會被模擬。

警告

這不會模擬在此之前匯入的模組。請不要忘記,ESM 中的所有靜態匯入總是 提升,因此在此之前放置這項內容不會強制它在匯入之前被呼叫

ts
vi.doMock('./increment.js') // this will be called _after_ the import statement

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

// the module is not mocked, because vi.doMock is not called yet
increment(1) === 2

let mockedIncrement = 100

beforeEach(() => {
  // you can access variables inside a factory
  vi.doMock('./increment.js', () => ({ increment: () => ++mockedIncrement }))
})

test('importing the next module imports mocked one', async () => {
  // original import WAS NOT MOCKED, because vi.doMock is evaluated AFTER imports
  expect(increment(1)).toBe(2)
  const { increment: mockedIncrement } = await import('./increment.js')
  // new dynamic import returns mocked module
  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 的類型輔助程式。只傳回傳遞的物件。

partialtrue 時,它會預期 Partial<T> 作為傳回值。預設情況下,這只會讓 TypeScript 相信第一層級的值已被模擬。您可以傳遞 { deep: true } 作為第二個引數,以告訴 TypeScript 整個物件已被模擬(如果實際上是這樣的話)。

ts
import example from './example.js'

vi.mock('./example.js')

test('1 + 1 equals 10', async () => {
  vi.mocked(example.calc).mockReturnValue(10)
  expect(example.calc(1, '+', 1)).toBe(10)
})

vi.importActual

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

匯入模組,繞過所有檢查,以判斷是否應模擬它。如果您想部分模擬模組,這可能會很有用。

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

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

vi.unmock

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

從模擬註冊中移除模組。所有呼叫 import 都會傳回原始模組,即使它之前已被模擬。此呼叫會提升至檔案頂端,因此它只會取消模擬在 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 is already mocked, because vi.mock is hoisted
increment(1) === 100

// this is hoisted, and factory is called before the import on line 1
vi.mock('./increment.js', () => ({ increment: () => 100 }))

// all calls are mocked, and `increment` always returns 100
increment(1) === 100
increment(30) === 100

// this is not hoisted, so other import will return unmocked module
vi.doUnmock('./increment.js')

// this STILL returns 100, because `vi.doUnmock` doesn't reevaluate a module
increment(1) === 100
increment(30) === 100

// the next import is unmocked, now `increment` is the original function that returns count + 1
const { increment: unmockedIncrement } = await import('./increment.js')

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

vi.resetModules

  • 類型: () => Vitest

透過清除所有模組的快取來重設模組註冊。這允許在重新匯入時重新評估模組。頂層匯入無法重新評估。可能有助於隔離測試之間發生區域狀態衝突的模組。

ts
import { vi } from 'vitest'

import { data } from './data.js' // Will not get reevaluated beforeEach test

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

test('change state', async () => {
  const mod = await import('./some/path.js') // Will get reevaluated
  mod.changeLocalState('new value')
  expect(mod.getLocalState()).toBe('new value')
})

test('module has old state', async () => {
  const mod = await import('./some/path.js') // Will get reevaluated
  expect(mod.getLocalState()).toBe('old value')
})

警告

不會重設模擬註冊。若要清除模擬註冊,請使用 vi.unmockvi.doUnmock

vi.dynamicImportSettled

等待所有匯入載入。很有用,如果您有同步呼叫開始匯入您無法以其他方式等待的模組。

ts
import { expect, test } from 'vitest'

// cannot track import because Promise is not returned
function renderComponent() {
  import('./component.js').then(({ render }) => {
    render()
  })
}

test('operations are resolved', async () => {
  renderComponent()
  await vi.dynamicImportSettled()
  expect(document.querySelector('.component')).not.toBeNull()
})

提示

如果在動態匯入期間啟動另一個動態匯入,此方法將等待直到所有匯入都已解決。

此方法還將在匯入解決後等待下一個 setTimeout 滴答,因此所有同步操作都應在解決時完成。

模擬函式和物件

此部分說明如何使用 方法模擬 和替換環境和全域變數。

vi.fn

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

在函式上建立間諜,儘管可以在沒有函式的情況下啟動。每次呼叫函式時,它都會儲存其呼叫參數、回傳值和執行個體。此外,您可以使用 方法 來控制其行為。如果未提供函式,模擬在呼叫時會傳回 undefined

ts
const  = .(() => 0)

()

().()
().(0)

.(5)

const  = ()
().(5)
().(2, 5)

vi.isMockFunction

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

檢查給定的參數是否為模擬函式。如果您使用 TypeScript,它還會縮小其類型。

vi.clearAllMocks

將對所有間諜呼叫 .mockClear()。這將清除模擬記錄,但不會將其實作重設為預設值。

vi.resetAllMocks

將對所有間諜呼叫 .mockReset()。這將清除模擬記錄,並將其實作重設為空函式(將傳回 undefined)。

vi.restoreAllMocks

將對所有間諜呼叫 .mockRestore()。這將清除模擬記錄,並將其實作重設為原始實作。

vi.spyOn

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

在物件的方法或 getter/setter 上建立間諜,類似於 vi.fn()。它會傳回 模擬函式

ts
let  = 0
const  = {
  : () => 42,
}

const  = .(, 'getApples').(() => )
 = 1

(.()).(1)

().()
().(1)

提示

您可以在 afterEach 中呼叫 vi.restoreAllMocks(或啟用 test.restoreMocks)以將所有方法還原為其原始實作。這將還原原始的 物件描述,因此您將無法變更方法的實作

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

vi.stubEnv 0.26.0+

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

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

ts
import { vi } from 'vitest'

// `process.env.NODE_ENV` and `import.meta.env.NODE_ENV`
// are "development" before calling "vi.stubEnv"

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

process.env.NODE_ENV === 'production'
import.meta.env.NODE_ENV === 'production'
// doesn't change other envs
import.meta.env.MODE === 'development'

提示

您也可以透過單純指定值來變更,但您將無法使用 vi.unstubAllEnvs 來還原前一個值

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

vi.unstubAllEnvs 0.26.0+

  • 類型: () => Vitest

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

ts
import { vi } from 'vitest'

// `process.env.NODE_ENV` and `import.meta.env.NODE_ENV`
// are "development" before calling 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()

// restores to the value that were stored before the first "stubEnv" call
process.env.NODE_ENV === 'development'
import.meta.env.NODE_ENV === 'development'

vi.stubGlobal

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

變更全域變數的值。你可以透過呼叫 vi.unstubAllGlobals 還原其原始值。

ts
import {  } from 'vitest'

// `innerWidth` is "0" before calling stubGlobal

.('innerWidth', 100)

 === 100
. === 100
// if you are using jsdom or happy-dom
. === 100

提示

你也可以透過將值指定給 globalThiswindow(如果你使用 jsdomhappy-dom 環境)來變更值,但你將無法使用 vi.unstubAllGlobals 還原原始值。

ts
globalThis.innerWidth = 100
// if you are using jsdom or happy-dom
window.innerWidth = 100

vi.unstubAllGlobals 0.26.0+

  • 類型: () => Vitest

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

ts
import { vi } from 'vitest'

const Mock = vi.fn()

// IntersectionObserver is "undefined" before calling "stubGlobal"

vi.stubGlobal('IntersectionObserver', Mock)

IntersectionObserver === Mock
global.IntersectionObserver === Mock
globalThis.IntersectionObserver === Mock
// if you are using jsdom or happy-dom
window.IntersectionObserver === Mock

vi.unstubAllGlobals()

globalThis.IntersectionObserver === undefined
'IntersectionObserver' in globalThis === false
// throws ReferenceError, because it's not defined
IntersectionObserver === undefined

偽造計時器

此區段說明如何使用 偽造計時器

vi.advanceTimersByTime

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

此方法會呼叫每個已啟動的計時器,直到傳遞指定的毫秒數或佇列為空,以先達成的為準。

ts
let  = 0
(() => .(++), 50)

.(150)

// log: 1
// log: 2
// log: 3

vi.advanceTimersByTimeAsync

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

此方法會呼叫每個已啟動的計時器,直到傳遞指定的毫秒數或佇列為空,以先達成的為準。這將包括非同步設定的計時器。

ts
let  = 0
(() => .().(() => .(++)), 50)

await .(150)

// log: 1
// log: 2
// log: 3

vi.advanceTimersToNextTimer

  • 類型: () => Vitest

將呼叫下一個可用的計時器。這有助於在每次計時器呼叫之間進行斷言。你可以串聯呼叫它以自行管理計時器。

ts
let  = 0
(() => .(++), 50)

.() // log: 1
  .() // log: 2
  .() // log: 3

vi.advanceTimersToNextTimerAsync

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

將呼叫下一個可用的計時器,並在非同步設定時等待它解析。對於在每個計時器呼叫之間進行斷言很有用。

ts
let  = 0
(() => .().(() => .(++)), 50)

await .() // log: 1
(.).(1)

await .() // log: 2
await .() // log: 3

vi.getTimerCount

  • 類型: () => number

取得等待計時器的數量。

vi.clearAllTimers

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

vi.getMockedSystemTime

  • 類型() => Date | null

傳回使用 setSystemTime 設定的模擬目前日期。如果日期沒有模擬,此方法將傳回 null

vi.getRealSystemTime

  • 類型() => number

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

vi.runAllTicks

  • 類型: () => Vitest

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

vi.runAllTimers

  • 類型: () => Vitest

此方法將呼叫每個已啟動的計時器,直到計時器佇列為空。這表示在 runAllTimers 期間呼叫的每個計時器都將被觸發。如果您有無限間隔,它將在嘗試 10,000 次後擲出 (可以使用 fakeTimers.loopLimit 設定)。

ts
let  = 0
(() => .(++))
const  = (() => {
  .(++)
  if ( === 3)
    ()
}, 50)

.()

// log: 1
// log: 2
// log: 3

vi.runAllTimersAsync

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

此方法將非同步呼叫每個已啟動的計時器,直到計時器佇列為空。這表示在 runAllTimersAsync 期間呼叫的每個計時器都將被觸發,即使是非同步計時器。如果您有無限間隔,它將在嘗試 10,000 次後擲出 (可以使用 fakeTimers.loopLimit 設定)。

ts
(async () => {
  .(await .('result'))
}, 100)

await .()

// log: result

vi.runOnlyPendingTimers

  • 類型: () => Vitest

此方法將呼叫在 vi.useFakeTimers 呼叫後啟動的每個計時器。它不會觸發在呼叫期間啟動的任何計時器。

ts
let  = 0
(() => .(++), 50)

.()

// log: 1

vi.runOnlyPendingTimersAsync

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

此方法將非同步呼叫在 vi.useFakeTimers 呼叫後啟動的每個計時器,即使是非同步計時器。它不會觸發在呼叫期間啟動的任何計時器。

ts
(() => {
  .(1)
}, 100)
(() => {
  .().(() => {
    .(2)
    (() => {
      .(3)
    }, 40)
  })
}, 10)

await .()

// log: 2
// log: 3
// log: 3
// log: 1

vi.setSystemTime

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

如果啟用假計時器,此方法模擬使用者變更系統時鐘 (將影響與日期相關的 API,例如 hrtimeperformance.nownew Date()) - 但是,它不會觸發任何計時器。如果未啟用假計時器,此方法將只模擬 Date.* 呼叫。

如果您需要測試任何依賴於目前日期的事物,這會很有用,例如 Luxon 在您的程式碼中呼叫。

ts
const  = new (1998, 11, 19)

.()
.()

(.()).(.())

.()

vi.useFakeTimers

  • 類型: (config?: FakeTimerInstallOpts) => Vitest

若要啟用模擬計時器,您需要呼叫此方法。它會封裝所有進一步呼叫的計時器(例如 setTimeoutsetIntervalclearTimeoutclearIntervalsetImmediateclearImmediateDate),直到呼叫 vi.useRealTimers() 為止。

在使用 --pool=forks 透過 node:child_process 執行 Vitest 時,不支援模擬 nextTick。NodeJS 在 node:child_process 內部使用 process.nextTick,且在模擬時會當機。在使用 --pool=threads 執行 Vitest 時,支援模擬 nextTick

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

提示

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

vi.isFakeTimers 0.34.5+

  • 類型: () => boolean

如果啟用虛假計時器,則傳回 true

vi.useRealTimers

  • 類型: () => Vitest

當計時器用完時,您可以呼叫此方法將模擬計時器還原為其原始實作。所有先前排定的計時器都將被捨棄。

其他

Vitest 提供的一組有用的輔助函數。

vi.waitFor 0.34.5+

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

等待回呼成功執行。如果回呼擲回錯誤或傳回遭拒絕的承諾,它將持續等待,直到成功或逾時為止。

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

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, // default is 1000
      interval: 20, // default is 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 () => {
  // start populating DOM
  populateDOMAsync()

  const element = await vi.waitFor(async () => {
    // try to get the element until it exists
    const element = await getDOMElementAsync() as HTMLElement | null
    expect(element).toBeTruthy()
    expect(element.dataset.initialized).toBeTruthy()
    return element
  }, {
    timeout: 500, // default is 1000
    interval: 20, // default is 50
  })
  expect(element).toBeInstanceOf(HTMLElement)
})

如果使用 vi.useFakeTimersvi.waitFor 會在每個檢查回呼中自動呼叫 vi.advanceTimersByTime(interval)

vi.waitUntil 0.34.5+

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

這類似於 vi.waitFor,但如果 callback 拋出任何錯誤,執行會立即中斷並收到錯誤訊息。如果 callback 回傳假值,下一次檢查會持續進行,直到回傳真值。這在需要在執行下一步之前等待某個東西存在時很有用。

請看以下範例。我們可以使用 vi.waitUntil 等待元素出現在頁面上,然後我們可以使用該元素執行某些操作。

ts
import { , ,  } from 'vitest'

('Element render correctly', async () => {
  const  = await .(
    () => .('.element'),
    {
      : 500, // default is 1000
      : 20, // default is 50
    }
  )

  // do something with the element
  (.('.element-child')).()
})

vi.hoisted 0.31.0+

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

ES 模組中的所有靜態 import 陳述式都會提升到檔案頂端,因此在 import 之前定義的任何程式碼實際上會在評估 import 之後執行。

不過,在 import 模組之前,呼叫一些副作用(例如模擬日期)會很有用。

若要繞過此限制,可以將靜態 import 改寫成動態 import,如下所示

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

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

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

此方法會傳回工廠回傳的值。如果需要輕鬆存取區域定義的變數,可以在 vi.mock 工廠中使用該值

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)

請注意,即使您的環境不支援頂層 await,此方法也可以非同步呼叫

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

vi.setConfig

  • 類型RuntimeConfig

更新目前測試檔案的設定。此方法僅支援會影響目前測試檔案的設定選項

ts
vi.setConfig({
  allowOnly: true,
  testTimeout: 10_000,
  hookTimeout: 10_000,
  clearMocks: true,
  restoreMocks: true,
  fakeTimers: {
    now: new Date(2021, 11, 19),
    // supports the whole object
  },
  maxConcurrency: 10,
  sequence: {
    hooks: 'stack'
    // supports only "sequence.hooks"
  }
})

vi.resetConfig

  • 類型RuntimeConfig

如果之前已呼叫 vi.setConfig,這會將設定重設為原始狀態。