測試速度飆升 10 倍!Vitest 帶來現代前端最強測試體驗

作者: Calpa Liu
字數:4714
出版:2025 年 5 月 2 日
測試不該拖慢開發流程,而 Vitest 正是讓你「寫測試像開發一樣快」的關鍵武器。還在用 Jest 等太久?Vitest 結合 Vite 高速構建與即時測試回饋,支援 TypeScript、Vue、React 等框架,全面升級你的測試流程!

什麼是 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 的優勢

  1. 速度優勢

Vitest 的一個主要優勢是其出色的性能。它建立在 Vite 之上,繼承了快速的轉換和開發服務能力,並具備智能的監視模式,只針對受代碼更改影響的測試進行重跑,顯著減少反饋循環時間。此外,Vitest 支援多進程並行執行測試文件,進一步提升測試效率。根據實際測試,Vitest 相較於 Jest 速度提升明顯,通常可快 30% 以上,尤其是在 TypeScript 代碼庫中。部分大型項目甚至有報告指出運行整個測試套件的速度可達 Jest 的 10 至 20 倍。

  1. 與 Vite 的無縫整合

對於使用 Vite 的項目,Vitest 能夠實現高度的無縫整合,開發者可以直接重用 Vite 的配置文件,無需為測試維護額外的設置。在開發、構建和測試流程中,所有的轉換管道與插件生態系統都能保持一致,充分發揮 Vite 的靈活性與高效性。這種深度整合不僅大幅簡化了測試環境的設置流程,也確保了開發與測試階段環境的一致性,從而有效減少因配置差異導致的各類問題。

  1. 現代化功能

Vitest 從設計之初就全面支持現代 JavaScript 開發實踐,原生支援 ES 模塊和頂層 await,並且允許在測試中直接使用 TypeScript 及 JSX 語法,無需繁瑣配置。這種現代化的技術棧讓開發者能夠無縫利用 Vite 的強大能力,輕鬆撰寫高效可維護的測試代碼。這些特性讓 Vitest 成為新一代 Web 開發項目的理想選擇,開發者可以放心運用最新的語法標準與工具,而不必擔心兼容性或額外的轉換步驟,大幅提升測試體驗與開發效率。

  1. 優秀的開發者體驗

Vitest 注重提供出色的開發者體驗,帶來與 Jest 兼容的熟悉 API,讓從其他測試框架遷移變得輕鬆簡單。對於 Vite 項目,開發者幾乎無需額外配置即可快速開始使用,同時享有清晰、易於理解的錯誤報告,能夠高效定位並解決問題。此外,Vitest 內建豐富的工具集,包括斷言、模擬與快照等功能,無需外部庫即可覆蓋大多數測試需求,顯著提升測試的靈活性和便捷性。

  1. 簡化配置

與 Jest 等傳統框架相比,Vitest 大幅簡化了測試配置。它為 ESM 及現代 JavaScript 項目減少了繁瑣的設定負擔,提供開箱即用的合理默認值,讓開發者能更快上手,無需花費大量時間進行手動調整。此外,Vitest 在開發、構建和測試階段皆可共用相同的配置文件,確保流程一致性並提升專案可維護性。這種一致的設定方式,有效減少了因環境差異導致的問題,使得整體開發體驗更加流暢。

Vitest 與 Jest 的比較

Vitest 與 Jest 作為兩個主流的測試框架,有許多不同點:

特性VitestJest
原生集成與 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,只需要幾個簡單的步驟:

  1. 安裝 Vitest
npm install -D vitest
  1. 創建測試文件
// math.test.js
import { expect, test } from 'vitest'
import { add } from './math'

test('addition works', () => {
  expect(add(2, 2)).toBe(4)
})
  1. 在 package.json 中添加測試腳本
{
  "scripts": {
    "test": "vitest"
  }
}
  1. 運行測試
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/reactrenderHook 可以掛載 hook 並直接存取返回值,搭配 act 操作更新狀態,觀察 count 是否如預期變化。這種測試方式能覆蓋 hooks 的狀態流與副作用邏輯,確保行為穩定可靠。

對於 Vue composables,可用 @vue/test-utilsmountsetup 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 的團隊。

想跟上前端開發的最新技術與實戰分享嗎?立即訂閱本站,掌握 React、Vue、TypeScript 等趨勢!
關於 Calpa

Calpa 擅長使用 TypeScriptReact.jsVue.js 建立 Responsive Website。

他積極參與開源社區,曾在 2019 年的香港開源大會上擔任講者,提供工作經驗和見解。此外,他也在 GitHub 上公開分享個人博客程式碼,已獲得超過 300 顆星星和 60 個分支的支持。

他熱愛學習新技術,並樂意分享經驗。他相信,唯有不斷學習才能跟上快速演變的技術環境。

熱門文章

最新文章