什麼是 Vitest?
Vitest 是一個原生支援 Vite 的下一代測試框架,專為現代 JavaScript 和 TypeScript 項目設計。它由 Vite 生態系統的核心開發者創建,旨在解決傳統測試框架(如 Jest)在現代 Web 開發中遇到的一些限制和效能問題。
作為一個 Vite 驅動的測試框架,Vitest 可以直接利用 Vite 的配置、轉換器、解析器和插件,使得測試環境與開發環境保持一致,從而減少了配置的重複和潛在的不一致問題。
// 一個簡單的 Vitest 測試示例
import { expect, test } from 'vitest'
import { add } from './math'
test('addition works', () => {
expect(add(2, 2)).toBe(4)
})
Vitest 的主要特點
Vitest 結合了 Vite 的極速構建能力與現代測試框架的多項創新特性,讓前端開發者能夠獲得近乎即時的測試反饋。它支援熱模組替換式的智能監視模式,僅針對受影響的測試進行快速重跑,極大提升開發效率。更重要的是,Vitest 能夠無縫重用 Vite 的配置、插件與轉譯器,確保測試環境與真實應用保持一致,減少配置重複和潛在錯誤。
在組件測試方面,Vitest 原生支援 Vue、React、Svelte、Lit、Marko 等主流框架,並且內建 TypeScript 與 JSX 處理能力,無需額外設置即可直接為現代 JavaScript/TypeScript 項目撰寫測試。此外,Vitest 提供多線程執行能力,利用 Tinypool 實現高效的工作池分流,保證大型專案也能獲得優異的測試性能。
Vitest 也內建 Chai 斷言庫並提供與 Jest 兼容的 expect API,支援快照測試、模擬(Mocking)、存根(Stubbing)、間諜(Spying)等功能,讓測試撰寫更加靈活全面。這些特性共同構成了一個現代化、易用且高效的前端測試解決方案。
適合使用 Vitest 的場景
Vitest 非常適合重視開發效率與現代技術棧一致性的團隊。其原生支援 TypeScript,讓專案無需額外配置即可取得完善的型別檢查;在 Monorepo 架構下,更能高效支援多工作區並行測試,滿足大型專案的需求。
此外,Vitest 也非常適合元件導向開發,能與 Vue、React 等主流框架無縫結合,進行單元或整合測試。在 CI/CD 自動化流程中,Vitest 可輕鬆與 Vite、Rollup、esbuild 等現代打包工具整合,提升部署流程的穩定性與可靠性。
Vitest 的優勢
- 速度優勢
Vitest 的一個主要優勢是其出色的性能。它建立在 Vite 之上,繼承了快速的轉換和開發服務能力,並具備智能的監視模式,只針對受代碼更改影響的測試進行重跑,顯著減少反饋循環時間。此外,Vitest 支援多進程並行執行測試文件,進一步提升測試效率。根據實際測試,Vitest 相較於 Jest 速度提升明顯,通常可快 30% 以上,尤其是在 TypeScript 代碼庫中。部分大型項目甚至有報告指出運行整個測試套件的速度可達 Jest 的 10 至 20 倍。
- 與 Vite 的無縫整合
對於使用 Vite 的項目,Vitest 能夠實現高度的無縫整合,開發者可以直接重用 Vite 的配置文件,無需為測試維護額外的設置。在開發、構建和測試流程中,所有的轉換管道與插件生態系統都能保持一致,充分發揮 Vite 的靈活性與高效性。這種深度整合不僅大幅簡化了測試環境的設置流程,也確保了開發與測試階段環境的一致性,從而有效減少因配置差異導致的各類問題。
- 現代化功能
Vitest 從設計之初就全面支持現代 JavaScript 開發實踐,原生支援 ES 模塊和頂層 await,並且允許在測試中直接使用 TypeScript 及 JSX 語法,無需繁瑣配置。這種現代化的技術棧讓開發者能夠無縫利用 Vite 的強大能力,輕鬆撰寫高效可維護的測試代碼。這些特性讓 Vitest 成為新一代 Web 開發項目的理想選擇,開發者可以放心運用最新的語法標準與工具,而不必擔心兼容性或額外的轉換步驟,大幅提升測試體驗與開發效率。
- 優秀的開發者體驗
Vitest 注重提供出色的開發者體驗,帶來與 Jest 兼容的熟悉 API,讓從其他測試框架遷移變得輕鬆簡單。對於 Vite 項目,開發者幾乎無需額外配置即可快速開始使用,同時享有清晰、易於理解的錯誤報告,能夠高效定位並解決問題。此外,Vitest 內建豐富的工具集,包括斷言、模擬與快照等功能,無需外部庫即可覆蓋大多數測試需求,顯著提升測試的靈活性和便捷性。
- 簡化配置
與 Jest 等傳統框架相比,Vitest 大幅簡化了測試配置。它為 ESM 及現代 JavaScript 項目減少了繁瑣的設定負擔,提供開箱即用的合理默認值,讓開發者能更快上手,無需花費大量時間進行手動調整。此外,Vitest 在開發、構建和測試階段皆可共用相同的配置文件,確保流程一致性並提升專案可維護性。這種一致的設定方式,有效減少了因環境差異導致的問題,使得整體開發體驗更加流暢。
Vitest 與 Jest 的比較
Vitest 與 Jest 作為兩個主流的測試框架,有許多不同點:
特性 | Vitest | Jest |
---|---|---|
原生集成 | 與 Vite 無縫集成 | 需要額外配置 |
現代語法支持 | 支持 ESM 導入、頂層 await | 對現代 JavaScript 語法支持有限 |
Monorepo 友好性 | 工作空間支持高效測試 | 在複雜的 monorepo 設置中可能較為繁瑣 |
可擴展性 | 通過插件擴展功能 | 擴展選項有限 |
TypeScript/JSX 支持 | 無縫集成 | 需要額外配置 |
源碼內測試 | 可選:保持測試靠近代碼 | 不支持 |
圖形界面儀表板 | 可選:可視化測試結果 | 不可用 |
處理測試波動 | 自動重試不穩定測試 | 需要額外配置 |
儘管 Jest 擁有更廣泛的社區支持和更多的文檔資源,但 Vitest 在速度、現代特性支持和與 Vite 整合方面具有明顯優勢。
如何從 Jest 遷移到 Vitest —— 完整指引
隨著前端測試生態的發展,越來越多團隊開始從 Jest 遷移到更現代、與 Vite 深度整合的 Vitest。兩者 API 高度相似,遷移過程極為順暢。以下將詳細對比常用 Mock API 並給出實際範例,協助你快速上手 Vitest。
Vitest 與 Jest 常用 Mock 語法對照表
在將測試從 Jest 遷移至 Vitest 時,Mock 相關的 API 幾乎一一對應,僅需將 jest
前綴換為 vi
,即可無痛轉換。下表列出常見用法對照,便於快速查找與替換。
常用語法對比
Jest 語法 | Vitest 語法 | 功能說明 |
---|---|---|
jest.spyOn() | vi.spyOn() | 建立間諜(Spy) |
jest.clearAllMocks() | vi.clearAllMocks() | 清除所有 mock 狀態 |
jest.resetAllMocks() | vi.resetAllMocks() | 重設所有 mock 狀態 |
jest.restoreAllMocks() | vi.restoreAllMocks() | 還原所有 mock |
jest.useFakeTimers() | vi.useFakeTimers() | 使用虛擬計時器 |
jest.runAllTimers() | vi.runAllTimers() | 執行所有定時器 |
jest.advanceTimersByTime() | vi.advanceTimersByTime() | 推進定時器 |
jest.setSystemTime() | vi.setSystemTime() | 設定系統時間 |
Mock 相關語法對比
Jest 語法 | Vitest 語法 | 功能說明 |
---|---|---|
jest.fn() | vi.fn() | 建立 mock 函數 |
jest.mock() | vi.mock() | 模擬整個模組 |
jest.fn().mockResolvedValue(val) | vi.fn().mockResolvedValue(val) | 模擬 Promise resolve |
jest.fn().mockRejectedValue(err) | vi.fn().mockRejectedValue(err) | 模擬 Promise reject |
備註:大多數時候直接將
jest
改成vi
即可。部分進階用法與限制請參考 Vitest Mocking 文件。
Mock 範例對比
在現代前端開發中,模擬(Mock)依賴是測試的重要一環。無論是 API 請求、第三方庫還是本地模組,透過 Mock 可以隔離外部依賴,專注於待測單元的邏輯。以下分別展示在 Jest 與 Vitest 下的 Mock 用法比較。
假設我們有一個 fetchData
函數從 ./api
模組導入,並希望在測試時模擬其回傳值:
import { fetchData } from './api'
jest.mock('./api')
test('should call fetchData and get mocked value', async () => {
fetchData.mockResolvedValue('ok')
const result = await fetchData()
expect(result).toBe('ok')
expect(fetchData).toHaveBeenCalled()
})
Jest 會自動將 ./api
的所有導出函數替換為 mock 函數,讓你可以自由設置回傳值或行為。
在 Vitest 中,Mock API 與 Jest 高度相容,只需將 jest
替換為 vi
,即可無縫遷移:
import { fetchData } from './api'
import { vi, test, expect } from 'vitest'
vi.mock('./api')
test('should call fetchData and get mocked value', async () => {
fetchData.mockResolvedValue('ok')
const result = await fetchData()
expect(result).toBe('ok')
expect(fetchData).toHaveBeenCalled()
})
Vitest 的 vi.mock
具備與 Jest 相同的自動 mock 行為,並支援更現代的語法糖與類型推斷(在 TypeScript 專案中尤為明顯)。此外,Vitest 內建多線程執行與更快速的冷/熱啟動能力,讓大量含有 Mock 的測試同樣能獲得極致效能。
Mock 生態與最佳實踐
Vitest 除了與 Jest API 兼容,還提供了豐富的 Mock 工具,如 vi.fn()
、vi.spyOn()
等,支援函數、物件、模組等多層級 Mock 需求,滿足複雜場景下的單元與整合測試。你可以使用 vi.resetAllMocks()
、vi.clearAllMocks()
等輕鬆管理 Mock 狀態,確保每個測試用例的獨立性。
無論是從 Jest 遷移或新專案導入,Vitest 都能讓現代前端測試更簡單、更高效。建議在團隊內實踐時,善用自動 Mock、間諜(Spy)、快照等先進特性,提升測試可靠性與開發體驗。
Vitest 的 API 設計充分考慮了與 Jest 的兼容性,讓現有測試遷移變得輕而易舉。只需簡單替換,即可享受更快的執行速度與 Vite 生態的便利。如果你正在使用 Vite 開發現代前端應用,不妨嘗試將測試框架升級至 Vitest,讓開發與測試體驗再上新層樓!
開始使用 Vitest
要開始使用 Vitest,只需要幾個簡單的步驟:
- 安裝 Vitest:
npm install -D vitest
- 創建測試文件:
// math.test.js
import { expect, test } from 'vitest'
import { add } from './math'
test('addition works', () => {
expect(add(2, 2)).toBe(4)
})
- 在 package.json 中添加測試腳本:
{
"scripts": {
"test": "vitest"
}
}
- 運行測試:
npm run test
各框架支援
Vue 專案如何實現極速現代化測試體驗
在現代 Vue 開發流程中,Vitest 徹底改變了單元測試體驗。Vitest 與 Vite 深度整合,讓 Vue 單文件元件(SFC)能即時、原生地測試,確保開發與測試環境完全一致。無論你使用 TypeScript、JSX 還是各類 Vite 插件,測試時都能享受和開發時相同的配置,消除設定分歧。
借助 @vue/test-utils
,你可以用直觀 API 掛載(mount)Vue 組件、模擬用戶互動、讀取或設置 props、觸發事件、檢查 DOM 結果,甚至結合快照測試,全面覆蓋 props 傳遞、slot 渲染、emits 邏輯與生命週期行為,構建現代 Vue 專案不可或缺的測試基礎設施。
範例:極簡測試一個典型 Vue 元件
<!-- HelloWorld.vue -->
<template>
<h1>Hello, {{ name }}!</h1>
</template>
<script setup lang="ts">
defineProps<{ name: string }>()
</script>
對應測試檔:
// HelloWorld.test.ts
import { describe, it, expect } from 'vitest'
import { mount } from '@vue/test-utils'
import HelloWorld from './HelloWorld.vue'
describe('HelloWorld', () => {
it('應正確渲染傳入的 name', () => {
const wrapper = mount(HelloWorld, {
props: { name: 'Vitest' }
})
expect(wrapper.text()).toContain('Hello, Vitest!')
})
})
Vitest 搭配 @vue/test-utils
,不僅能輕鬆掛載元件、模擬事件、做快照測試,還能快速驗證 props、emits、slot 及生命週期邏輯。加上 Vite 帶來的即時響應與極速執行,Vue 測試工作從未如此流暢高效。無論日常開發還是 CI/CD 流程,Vitest 都是現代 Vue 專案提升品質與信心的首選利器。
React 開發者該如何用好 Vitest?
React 已成為現代前端開發的中流砥柱,Vitest 則帶來前所未有的測試新體驗。如果你曾為 Jest + Babel + TypeScript 的複雜設定煩惱,Vitest 與 Vite 的深度整合將帶給你驚喜——TypeScript 和 JSX 渲染毫無阻礙,React 元件測試自然順暢。
無論是撰寫元件測試、打造 custom hook、驗證 Context 邏輯,還是用 React Testing Library 進行端到端互動模擬,Vitest 都讓過程更快更直覺。API 易懂、快照與 mock 功能完善,讓你專注產品本身,不被工具鏈拖慢腳步。
範例:Vitest 搭配 @testing-library/react
讓測試變得親切
import { render, screen, fireEvent } from '@testing-library/react'
import { describe, it, expect, vi } from 'vitest'
import Button from './Button'
describe('Button 元件', () => {
it('應該正確渲染傳入的 label', () => {
render(<Button label="送出" />)
expect(screen.getByText('送出')).toBeInTheDocument()
})
it('點擊時應呼叫 onClick 處理函數', () => {
const handleClick = vi.fn()
render(<Button label="點我" onClick={handleClick} />)
fireEvent.click(screen.getByText('點我'))
expect(handleClick).toHaveBeenCalledTimes(1)
})
})
Vitest 讓你輕鬆驗證元件渲染、hooks、副作用、用戶互動與非同步流程,速度極快。開發與重構過程中,測試自然融入日常,讓 React 專案品質與團隊信心同步提升,開發體驗更流暢。
React/Vue/Svelte Hooks 測試
Vitest 支援現代前端框架的 hooks/composables 單元測試,讓你能直接驗證自定義邏輯的狀態與副作用。以下以 React custom hook 為例,說明如何編寫測試:
// useCounter.ts
import { useState } from 'react'
/**
* 自定義計數 hook
* @param initial 初始計數值
* @returns 當前 count、遞增 inc、遞減 dec 方法
*/
export function useCounter(initial = 0) {
const [count, setCount] = useState(initial)
const inc = () => setCount((c) => c + 1)
const dec = () => setCount((c) => c - 1)
return { count, inc, dec }
}
這個 hook 封裝了簡單的計數邏輯,能傳入初始值並提供遞增/遞減操作。
// useCounter.test.tsx
import { renderHook, act } from '@testing-library/react'
import { describe, it, expect } from 'vitest'
import { useCounter } from './useCounter'
describe('useCounter hook', () => {
it('能正確遞增與遞減計數值', () => {
const { result } = renderHook(() => useCounter(5))
expect(result.current.count).toBe(5)
act(() => result.current.inc())
expect(result.current.count).toBe(6)
act(() => result.current.dec())
expect(result.current.count).toBe(5)
})
})
說明:
利用 @testing-library/react
的 renderHook
可以掛載 hook 並直接存取返回值,搭配 act
操作更新狀態,觀察 count 是否如預期變化。這種測試方式能覆蓋 hooks 的狀態流與副作用邏輯,確保行為穩定可靠。
對於 Vue composables,可用 @vue/test-utils
的 mount
或 setup
API 進行同類型測試,確保組件外部邏輯同樣具備高可測性與可維護性。
更多例子與說明
以下將以實際範例解釋 Vitest 如何應對各種現代前端測試需求。
1. async/await 支援
Vitest 原生支援 async/await,允許你直接針對非同步函數進行測試,並自動處理 Promise 的完成與失敗。這使測試非同步 API 或資料請求變得直覺且簡潔。
import { expect, test } from 'vitest'
import { fetchData } from './api'
// 測試 fetchData 是否正確回傳包含 'hello' 的字串
test('fetchData returns correct value', async () => {
const data = await fetchData()
expect(data).toContain('hello')
})
說明:
只需將測試函數標記為 async
,即可在內部直接使用 await
。Vitest 會自動等待 Promise 完成後再判斷測試結果。
2. TypeScript 型別檢查
Vitest 可無縫整合 TypeScript,讓你直接在測試中享受型別推斷與型別檢查,提升測試可靠性。
import type { User } from './types'
import { getUser } from './user'
import { expect, test } from 'vitest'
// 確保 getUser 回傳的物件符合 User 型別並具備必要屬性
test('getUser returns a User object', () => {
const user: User = getUser(1)
expect(user).toHaveProperty('id')
expect(user).toHaveProperty('name')
})
說明:
利用 TypeScript 的型別系統,可以及早發現資料結構錯誤,避免型別不一致導致的潛在 bug。
3. 模擬函數(Mocking)
Vitest 內建強大的 mocking 能力,支援 spy、mock 及 stub 等常見需求,讓測試可控且獨立。
import { vi, test, expect } from 'vitest'
import { fetchUser } from './user'
import * as api from './api'
// 測試 fetchUser 是否正確調用 api.get 並回傳預期資料
test('fetchUser calls api.get', async () => {
const spy = vi.spyOn(api, 'get').mockResolvedValue({ id: 1, name: 'Calpa' })
const user = await fetchUser(1)
expect(spy).toHaveBeenCalledWith(1)
expect(user.name).toBe('Calpa')
spy.mockRestore()
})
說明:
使用 vi.spyOn
可以攔截並模擬目標函數的行為,方便我們驗證調用參數與回傳結果,而不需要真正執行 API 請求。
這些例子展示了 Vitest 在現代前端開發中的靈活性與強大功能,無論是處理非同步程式、型別安全,還是模擬外部依賴,都能輕鬆勝任。
與生態系工具整合
Vitest 支援與主流前端測試與開發工具深度整合,極大促進高效且現代化的測試工作流程。舉例來說,你可以將 Vitest 與 Testing Library 結合,針對 React、Vue、Svelte 等框架進行元件渲染與用戶互動測試,模擬點擊、輸入等行為,驗證 UI 是否根據業務邏輯正確響應。此外,Vitest 能與 Cypress 等端對端(E2E)測試工具協作,分工明確:由 Vitest 負責單元及元件層級測試,Cypress 負責完整用戶流程驗證,讓整體測試結構更清晰、維護更容易。
在測試覆蓋率方面,Vitest 可無縫搭配 c8、istanbul 等覆蓋率工具,生成 HTML、LCOV 等多種格式的詳細覆蓋報告,不僅顯示哪些檔案、函式或分支尚未被測試,還能結合 CI/CD 流程,於 pull request 階段自動檢查覆蓋標準,協助團隊及時發現測試盲區,提升整體專案的健壯性。
此外,Vitest 測試文件與 ESLint、Prettier 等程式碼品質工具可以深度集成,支援自動格式化、即時靜態檢查,確保測試程式碼與生產程式碼風格一致、規範統一。對於大型團隊,這種整合有助於減少技術債、提升可維護性,並在敏捷開發流程中實現高效、可靠的自動化測試體驗。無論是新專案啟動還是傳統專案遷移,Vitest 都能與現有生態工具協同工作,打造現代前端開發中的最佳測試基礎設施。
結論
Vitest 作為一個現代化的測試框架,通過與 Vite 的緊密整合、優秀的性能和簡化的配置,為開發者提供強大的測試解決方案。不僅適合新 Vite 項目,也是傳統 Jest 用戶的理想替代。隨著越來越多項目採用 Vite,Vitest 有望成為 JavaScript 生態中的主流測試框架之一。其速度、現代特性支持與優秀開發者體驗,使其成為現代 Web 開發值得考慮的重要工具,無論是新專案還是現有專案升級測試框架,尤其推薦給已經或即將採用 Vite 的團隊。