跳到內容

遷移指南

從 Vitest 0.34.6 遷移

最低需求

Vitest 1.0 需要 Vite 5.0 和 Node.js 18 或更高版本。

所有 @vitest/* 子套件都需要 Vitest 版本 1.0。

快照更新 #3961

快照中的引號不再轉譯,且所有快照都使用反引號 (`),即使字串只有一行。

  1. 引號不再轉譯
diff
expect({ foo: 'bar' }).toMatchInlineSnapshot(`
  Object {
-    \\"foo\\": \\"bar\\",
+    "foo": "bar",
  }
`)
  1. 單行快照現在使用 "`" 引號,而不是 '
diff
- expect('some string').toMatchInlineSnapshot('"some string"')
+ expect('some string').toMatchInlineSnapshot(`"some string"`)

@vitest/snapshot 套件也有 變更。如果您沒有直接使用它,則不需要變更任何內容。

  • 您不再需要延伸 SnapshotClient 只為覆寫 equalityCheck 方法:只要在初始化實例時將其傳遞為 isEqual 即可
  • client.setTest 已重新命名為 client.startCurrentRun
  • client.resetCurrent 已重新命名為 client.finishCurrentRun

池已標準化 #4172

我們移除了許多組態選項,以簡化根據您的需求組態執行器的過程。如果您依賴 --threads 或其他相關旗標,請查看遷移範例。

  • --threads 現在是 --pool=threads
  • --no-threads 現在是 --pool=forks
  • --single-thread 現在是 --poolOptions.threads.singleThread
  • --experimental-vm-threads 現在是 --pool=vmThreads
  • --experimental-vm-worker-memory-limit 現在是 --poolOptions.vmThreads.memoryLimit
  • --isolate 現在是 --poolOptions.<pool-name>.isolatebrowser.isolate
  • test.maxThreads 現在是 test.poolOptions.<pool-name>.maxThreads
  • test.minThreads 現在是 test.poolOptions.<pool-name>.minThreads
  • test.useAtomics 現在是 test.poolOptions.<pool-name>.useAtomics
  • test.poolMatchGlobs.child_process 現在是 test.poolMatchGlobs.forks
  • test.poolMatchGlobs.experimentalVmThreads 現在是 test.poolMatchGlobs.vmThreads
diff
{
  scripts: {
-    "test": "vitest --no-threads"
     // For identical behaviour:
+    "test": "vitest --pool forks --poolOptions.forks.singleFork"
     // Or multi parallel forks:
+    "test": "vitest --pool forks"

  }
}
diff
{
  scripts: {
-    "test": "vitest --experimental-vm-threads"
+    "test": "vitest --pool vmThreads"
  }
}
diff
{
  scripts: {
-    "test": "vitest --isolate false"
+    "test": "vitest --poolOptions.threads.isolate false"
  }
}
diff
{
  scripts: {
-    "test": "vitest --no-threads --isolate false"
+    "test": "vitest --pool forks --poolOptions.forks.isolate false"
  }
}

涵蓋範圍變更 #4265, #4442

選項 coverage.all 現在預設啟用。這表示所有符合 coverage.include 樣式的專案檔案都將被處理,即使它們未執行。

涵蓋範圍閾值的 API 形狀已變更,現在支援使用全域樣式為特定檔案指定閾值

diff
export default defineConfig({
  test: {
    coverage: {
-      perFile: true,
-      thresholdAutoUpdate: true,
-      100: true,
-      lines: 100,
-      functions: 100,
-      branches: 100,
-      statements: 100,
+      thresholds: {
+        perFile: true,
+        autoUpdate: true,
+        100: true,
+        lines: 100,
+        functions: 100,
+        branches: 100,
+        statements: 100,
+      }
    }
  }
})

模擬類型 #4400

已移除一些類型,改用 Jest 風格的「模擬」命名。

diff
- import { EnhancedSpy, SpyInstance } from 'vitest'
+ import { MockInstance } from 'vitest'

警告

SpyInstance 已過時,改用 MockInstance,並將在下一個主要版本中移除。

計時器模擬 #3925

vi.useFakeTimers() 不再自動模擬 process.nextTick。仍可透過明確指定 vi.useFakeTimers({ toFake: ['nextTick'] }) 來模擬 process.nextTick

不過,在使用 --pool=forks 時無法模擬 process.nextTick。如果您需要模擬 process.nextTick,請使用其他 --pool 選項。

從 Jest 遷移

Vitest 採用與 Jest 相容的 API 設計,目的是讓從 Jest 移轉的過程盡可能簡單。儘管如此,您仍可能會遇到以下差異

預設為全域變數

Jest 預設啟用 全域變數 API。Vitest 則沒有。您可以透過 globals 設定 啟用全域變數,或更新程式碼以使用從 vitest 模組匯入的內容。

如果您決定停用全域變數,請注意像 testing-library 等常見函式庫將不會執行自動 DOM 清理

模擬模組

在 Jest 中模擬模組時,工廠參數的回傳值是預設匯出。在 Vitest 中,工廠參數必須回傳一個物件,其中每個匯出都明確定義。例如,以下 jest.mock 必須更新如下

ts
jest.mock('./some-path', () => 'hello') 
vi.mock('./some-path', () => ({ 
  default: 'hello', 
})) 

如需更多詳細資訊,請參閱 vi.mock API 區段

自動模擬行為

與 Jest 不同的是,<root>/__mocks__ 中的模擬模組不會載入,除非呼叫 vi.mock()。如果您需要在每個測試中模擬它們,就像在 Jest 中一樣,您可以在 setupFiles 中模擬它們。

匯入模擬套件的原始檔

如果您只部分模擬套件,您可能之前使用過 Jest 的函式 requireActual。在 Vitest 中,您應該用 vi.importActual 取代這些呼叫。

ts
const { cloneDeep } = jest.requireActual('lodash/cloneDeep') 
const { cloneDeep } = await vi.importActual('lodash/cloneDeep') 

將模擬擴充至外部函式庫

Jest 預設會執行此動作,當模擬模組並希望將此模擬擴充至使用相同模組的其他外部函式庫時,您應該明確指出要模擬哪個第三方函式庫,以便外部函式庫透過使用 server.deps.inline 成為您的原始程式碼的一部分。

server.deps.inline: ["lib-name"]

存取模擬 Promise 的回傳值

Jest 和 Vitest 都會將所有模擬呼叫的結果儲存在 mock.results 陣列中,其中每個呼叫的回傳值儲存在 value 屬性中。然而,當模擬或監控 Promise(例如使用 mockResolvedValue)時,在 Jest 中 value 屬性會是一個 Promise,而在 Vitest 中,當 Promise 解析時,它會變成已解析的值。

ts
await expect(spy.mock.results[0].value).resolves.toBe(123) 
expect(spy.mock.results[0].value).toBe(123) 

環境變數

如同 Jest,如果 Vitest 之前未設定,則會將 NODE_ENV 設為 test。Vitest 也有 JEST_WORKER_ID 的對應項,稱為 VITEST_POOL_ID(始終小於或等於 maxThreads),因此如果您依賴它,請不要忘記重新命名它。Vitest 也公開了 VITEST_WORKER_ID,它是正在執行的工作程序的唯一 ID - 這個數字不受 maxThreads 影響,並且會隨著每個建立的工作程序而增加。

取代屬性

如果您想要修改物件,您將在 Jest 中使用 replaceProperty API,您可以在 Vitest 中使用 vi.stubEnvvi.spyOn 來執行相同的操作。

完成回呼

從 Vitest v0.10.0 開始,宣告測試的回呼樣式已棄用。您可以將它們改寫為使用 async/await 函式,或使用 Promise 模擬回呼樣式。

it('should work', (done) => {
it('should work', () => new Promise(done => {
  // ...
  done()
})
}))

掛鉤

beforeAll/beforeEach 掛鉤可能會在 Vitest 中傳回 中斷函式。因此,如果您傳回 undefinednull 以外的內容,您可能需要改寫掛鉤宣告。

ts
beforeEach(() => setActivePinia(createTestingPinia())) 
beforeEach(() => { setActivePinia(createTestingPinia()) }) 

在 Jest 中,掛鉤會依序呼叫(一個接著一個)。預設情況下,Vitest 會並行執行掛鉤。若要使用 Jest 的行為,請更新 sequence.hooks 選項

ts
export default defineConfig({
  test: {
    sequence: { 
      hooks: 'list', 
    } 
  }
})

類型

Vitest 沒有等同於 jest 名稱空間,因此您需要直接從 vitest 匯入類型

ts
let fn: jest.Mock<string, [string]> 
import type { Mock } from 'vitest'
let fn: Mock<[string], string> 

此外,Vitest 的第一個參數為 Args 類型,而不是 Returns,如您在 diff 中所見。

計時器

Vitest 不支援 Jest 的舊版計時器。

逾時

如果您使用 jest.setTimeout,您需要移轉到 vi.setConfig

ts
jest.setTimeout(5_000) 
vi.setConfig({ testTimeout: 5_000 }) 

Vue 擷取快照

這不是 Jest 特有的功能,但如果你之前使用 Jest 與 vue-cli 預設值,你將需要安裝 jest-serializer-vue 套件,並在 setupFiles 中使用它

vite.config.js

js
import {  } from 'vite'

export default ({
  : {
    : ['./tests/unit/setup.js']
  }
})

tests/unit/setup.js

js
import vueSnapshotSerializer from 'jest-serializer-vue'

expect.addSnapshotSerializer(vueSnapshotSerializer)

否則你的快照將會有許多跳脫的 " 字元。