遷移指南
從 Vitest 0.34.6 遷移
最低要求
Vitest 1.0 需要 Vite 5.0 和 Node.js 18 或更高版本。
所有 @vitest/*
子套件都需要 Vitest 1.0 版本。
快照更新 #3961
快照中的引號不再逸出,並且所有快照都使用反引號 (`),即使字串只有一行。
- 引號不再轉義:
expect({ foo: 'bar' }).toMatchInlineSnapshot(`
Object {
- \\"foo\\": \\"bar\\",
+ "foo": "bar",
}
`)
- 單行快照現在使用反引號 "`" 取代單引號 ':
- expect('some string').toMatchInlineSnapshot('"some string"')
+ expect('some string').toMatchInlineSnapshot(`"some string"`)
@vitest/snapshot
套件也進行了變更。如果您沒有直接使用它,則無需進行任何變更。
- 您不再需要僅僅為了覆寫
equalityCheck
方法而擴展SnapshotClient
:只需在初始化實例時將其作為isEqual
傳遞即可 client.setTest
已重新命名為client.startCurrentRun
client.resetCurrent
已重新命名為client.finishCurrentRun
Pool 標準化 #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>.isolate
和browser.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
{
scripts: {
- "test": "vitest --no-threads"
// For identical behaviour:
+ "test": "vitest --pool forks --poolOptions.forks.singleFork"
// Or multi parallel forks:
+ "test": "vitest --pool forks"
}
}
{
scripts: {
- "test": "vitest --experimental-vm-threads"
+ "test": "vitest --pool vmThreads"
}
}
{
scripts: {
- "test": "vitest --isolate false"
+ "test": "vitest --poolOptions.threads.isolate false"
}
}
{
scripts: {
- "test": "vitest --no-threads --isolate false"
+ "test": "vitest --pool forks --poolOptions.forks.isolate false"
}
}
Coverage 變更 #4265, #4442
選項 coverage.all
現在預設為啟用。這表示即使未執行,也會處理所有符合 coverage.include
樣式的專案檔案。
Coverage 臨界值 API 的結構已變更,現在支援使用 glob 樣式為特定檔案指定臨界值:
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,
+ }
}
}
})
Mock 類型變更 #4400
為了採用 Jest 風格的 "Mock" 命名,移除了一些類型。
- import { EnhancedSpy, SpyInstance } from 'vitest'
+ import { MockInstance } from 'vitest'
WARNING
SpyInstance
已棄用,建議使用 MockInstance
,並將在下一個主要版本中移除。
Timer Mock #3925
vi.useFakeTimers()
不再自動 mock process.nextTick
。仍然可以透過使用 vi.useFakeTimers({ toFake: ['nextTick'] })
明確地指定來 mock process.nextTick
。
但是,使用 --pool=forks
時無法 mock process.nextTick
。如果您需要 process.nextTick
mocking,請使用不同的 --pool
選項。
從 Jest 遷移
Vitest 的設計採用與 Jest 相容的 API,以便盡可能簡化從 Jest 的遷移。儘管做出了這些努力,您仍然可能會遇到以下差異:
預設使用全域變數
Jest 預設啟用其 globals API。Vitest 則否。您可以透過 the globals
configuration setting 啟用全域變數,或更新您的程式碼以使用從 vitest
模組匯入的內容。
如果您決定保持停用全域變數,請注意,像 testing-library
這樣的常見函式庫將不會執行自動 DOM cleanup。
Mock 模組
在 Jest 中 mock 模組時,工廠函數參數的傳回值是預設匯出。在 Vitest 中,工廠函數參數必須傳回一個物件,其中明確定義了每個匯出。例如,以下 jest.mock
必須更新如下:
jest.mock('./some-path', () => 'hello');
vi.mock('./some-path', () => ({
default: 'hello',
}));
如需更多詳細資訊,請參閱 vi.mock
api section。
自動 Mock
與 Jest 不同,除非呼叫 vi.mock()
,否則不會載入 <root>/__mocks__
中的 mock 模組。如果您需要在每個測試中都模擬它們,就像在 Jest 中一樣,您可以在 setupFiles
中進行模擬。
匯入 Mock 套件的原始版本
如果您僅部分 mock 套件,您可能之前使用過 Jest 的函式 requireActual
。在 Vitest 中,您應該將這些呼叫替換為 vi.importActual
。
const { cloneDeep } = jest.requireActual('lodash/cloneDeep');
const { cloneDeep } = await vi.importActual('lodash/cloneDeep');
擴展 Mock 到外部函式庫
在預設情況下,Jest 會在模擬模組並希望將此模擬擴展到使用相同模組的其他外部函式庫時,您應該明確告知要模擬哪個第三方函式庫,以便外部函式庫成為您原始碼的一部分,方法是使用 server.deps.inline。
server.deps.inline: ["lib-name"]
存取 Mock Promise 傳回值
Jest 和 Vitest 都將所有 mock 呼叫的結果儲存在 mock.results
陣列中,其中每個呼叫的傳回值都儲存在 value
屬性值中。 但是,當 mock 或 spy on promise(例如,使用 mockResolvedValue
)時,在 Jest 中,value
屬性值將是一個 promise,而在 Vitest 中,當 promise 被解析時,它將成為一個已解析的值。
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,您可以使用 vi.stubEnv
或 vi.spyOn
在 Vitest 中執行相同的操作。
Done Callback
從 Vitest v0.10.0 開始,宣告測試的回呼風格已被棄用。您可以重寫它們以使用 async
/await
函式,或使用 Promise 來模擬回呼風格。
it('should work', (done) => { // [!code --]
it('should work', () => new Promise(done => { // [!code ++]
// ...
done()
}) // [!code --]
})) // [!code ++]
鉤子
beforeAll
/beforeEach
鉤子 可以在 Vitest 中傳回 拆卸函數。因此,如果您的 hooks 傳回 undefined
或 null
以外的內容,您可能需要重寫您的 hooks 宣告:
beforeEach(() => setActivePinia(createTestingPinia()));
beforeEach(() => {
setActivePinia(createTestingPinia());
});
在 Jest 中,hooks 是依序呼叫的(一個接一個)。預設情況下,Vitest 並行執行 hooks。若要使用 Jest 的行為,請更新 sequence.hooks
選項:
export default defineConfig({
test: {
sequence: {
hooks: 'list',
},
},
});
Types
Vitest 沒有與 jest
命名空間等效的內容,因此您需要直接從 vitest
匯入類型:
let fn: jest.Mock<string, [string]>;
import type { Mock } from 'vitest';
let fn: Mock<[string], string>;
此外,如您在 diff 中所見,Vitest 將 Args
類型作為第一個引數,而不是 Returns
。
Timers
Vitest 不支援 Jest 的舊版 timers。
逾時
如果您使用 jest.setTimeout
,則需要遷移到 vi.setConfig
:
jest.setTimeout(5_000);
vi.setConfig({ testTimeout: 5_000 });
Vue Snapshots
這不是 Jest 特有的功能,但如果您之前將 Jest 與 vue-cli 預設一起使用,您需要安裝 jest-serializer-vue
套件,並在 setupFiles 中使用它:
vite.config.js
import { defineConfig } from 'vite';
export default defineConfig({
test: {
setupFiles: ['./tests/unit/setup.js'],
},
});
tests/unit/setup.js
import vueSnapshotSerializer from 'jest-serializer-vue';
expect.addSnapshotSerializer(vueSnapshotSerializer);
否則,您的快照將包含大量轉義的 "
字元。