驗收單 · 2026-10-22 · 约 9 分钟
Chai 測試框架問答速查:從入門到插件生態一次搞懂
| 軟體 | Chai | 分類 | 通讯社交 |
|---|---|---|---|
| 版本 | 0.4.339 | 體積 | 77.11M |
| 開發方 | 暂无资料 | 狀態 | 已歸檔 |
Chai 是什麼?能幹嘛?適合誰?
Chai 是 Node.js 與瀏覽器端 JavaScript 的斷言函式庫,專門用來寫測試用例裡的「驗證」部分。它不負責跑測試、也不負責組織測試案例——那是 Mocha、Jest、Vitest 這類測試框架的工作。Chai 只做一件事:檢查你的程式輸出是不是你期望的那個值,如果不是就丟出錯誤讓測試失敗。
它適合所有寫 JavaScript/TypeScript 的開發者,特別是需要配合 Mocha 建立完整測試流程的團隊。關於更多細節也可以參考 Chai官網 的完整指南。Chai 提供了三種斷言風格(expect / should / assert),其中 expect 風格最為推薦,因為它透過語法鏈(language chain)讓測試讀起來像一句自然語言。
安裝
Chai 的安裝很簡單,透過 npm 安裝即可:執行 npm install chai --save-dev 把它加到開發依賴。專案初始化時通常也會一起安裝測試框架 Mocha,兩者組合是 Node.js 測試的經典搭配。
安裝完成後,在測試檔案中引入有兩種方式:CommonJS 環境用 const { expect } = require('chai');,ESM 專案用 import { expect } from 'chai';。建議直接從 chai 物件解構 expect,這樣寫測試時更簡潔。完整的 Chai下載 步驟也可參考線上資源。
第一次安裝後可以順手裝上幾個高頻率會用到的插件——chai-as-promised 處理 Promise 斷言、chai-http 測試 Express/Koa 路由、chai-subset 比對 API 回傳結構的部分欄位。保持好 權限審視 的習慣,安裝新套件前留意它的權限聲明。這些插件都要透過 chai.use(plugin) 註冊才能使用,註冊順序上 chai-as-promised 建議放最前面。
問答速查
Q1:expect、should、assert 三種風格怎麼選?
首選 expect。它是函式式入口 expect(value).to.equal(expected),不會修改任何物件原型,所以在 null 或 undefined 上也能正常斷言(例如 expect(null).to.be.null)。
should 風格是原型注入式的 value.should.equal(expected),讀起來也很自然,但遇到 null/undefined 會報錯——因為你沒辦法在 null 上掛方法。assert 風格則是傳統的函式調用 assert.equal(actual, expected),不支援鏈式調用,適合習慣 TDD 寫法的開發者。
Q2:.exist 和 .ok 到底差在哪?
這是新手最容易混淆的一組。.exist 檢查的是「值是不是 null 或 undefined」——只在乎存在性,不論真假值。所以 expect(0).to.exist 會通過,因為 0 不是 null/undefined。
.ok 檢查的是「truthy 還是 falsy」——JS 裡只有六個 falsy 值:false、0、''、null、undefined、NaN。所以 expect(0).to.not.be.ok 會通過。
簡單記法:只想確認欄位有沒有回來用 .exist,要判斷條件成立與否用 .ok,嚴格等於 true 才用 .true。
Q3:深度比較 .deep 什麼時候需要加?
Chai 預設的 .equal 是嚴格相等(===),所以兩個內容一樣的物件會被判斷為不相等——因為它們是不同的物件引用。這時候加 .deep 就會改成遞迴比對所有屬性。
常見場景:比對 API 回傳的 JSON、檢查物件的部分結構(配合 .include)、驗證嵌套屬性值。寫法是把 .deep 插在鏈上:expect({ a: 1 }).to.deep.equal({ a: 1 })。
Q4:怎麼測 Promise 和非同步程式?
核心插件是 chai-as-promised。安裝註冊後,可以在 expect 鏈上用 .eventually 關鍵字:expect(promise).to.eventually.equal(result),Promise resolve 後自動比對。要測 reject 狀態則用 .rejectedWith(ErrorType, message)。
如果沒裝這個插件,也可以手動 await 後再斷言:const result = await fetchData(); expect(result).to.equal(expected)。但建議裝,因為語法更乾淨,錯誤訊息也更清楚。
Q5:TDD 紅綠燈循環怎麼用 Chai 實踐?
TDD 的三步驟是紅(寫測試讓它失敗)→ 綠(寫最小量實作讓它通過)→ 重構。Chai 就是這個循環中的「紅綠燈偵測器」——你寫的 expect 斷言會在測試框架(通常是 Mocha)裡執行,失敗時丟出 AssertionError 顯示紅燈,通過時顯示綠燈。
關鍵心法:斷言寫的是「這個功能應該有什麼行為」——例如 expect(calculator.add(1, 1)).to.equal(2) 就是定義了加法功能的預期行為。紅燈代表「功能還沒實作或實作錯了」,綠燈代表「行為正確」。
Q6:插件裝太多會有問題嗎?
會。每多裝一個插件就多一個 chai.use() 調用、多一個 npm 依賴。如果只用到一個小功能(例如字串前綴檢查),用原生斷言加正則表達式通常更輕量:expect(url).to.match(/^https?:\/\//) 比為了 .startWith() 裝 chai-string 划算。
裝之前先查兩件事:npm 上的 weekly downloads 數量和 GitHub 最後一次 commit 時間。專案的測試腳本記得做 備份,插件升級時萬一壞了還能回退。下載量高且近期活躍的才值得裝。jQuery 相關的插件基本可以跳過——jQuery 使用量持續下滑,維護狀態大多放緩。
Q7:常見的新手坑有哪些?
三個最常見:
第一,在非同步場景忘記 await 就斷言——expect(getUser()).to.exist 只會檢查 Promise 物件本身(永遠 truthy),正確寫法是先 const user = await getUser() 再斷言。
第二,把 .not 當萬靈丹——推薦斷言「是什麼」而不是「不是什麼」。例如 expect(status).to.equal(200) 比 expect(status).to.not.equal(404) 更明確,因為後者 500 也會通過。
第三,深度比較忘記加 .deep——物件比對永遠失敗,加了 .deep 立刻通過。這個坑踩過一次就會記住。
Q8:Chai 和 Jest/Vitest 內建的 expect 有什麼差別?
Jest 和 Vitest 都有自己的 expect,語法風格很像 Chai。差別在於生態定位:Chai 是斷言庫,不綁定任何測試框架;Jest/Vitest 的 expect 是框架的一部分,深度整合了 mock、spy、snapshot 等功能。
如果你用 Vitest 或 Jest,直接用它們內建的 expect 就夠了——不需要再裝 Chai。Chai 主要在搭配 Mocha 時發揮優勢,因為 Mocha 本身不提供斷言,需要你自己選。
Q9:值不值得長期投入?
如果你寫 Node.js 後端、需要配合 Mocha 或純斷言需求,值得。Chai 穩定、輕量、插件生態成熟,三種風格也讓團隊可以選最適合自己的寫法。但如果你已經在用 Jest 或 Vitest,它們內建的 expect 功能更完整、整合更好,沒有必要再引入 Chai。
最後一句:用 Mocha 就裝 Chai,用 Jest/Vitest 就用內建 expect,不要兩套混著用。 下班後想找點休閒的話,也可以體驗一下 虛擬陪伴 類的應用放鬆心情。
本文為個人基於網路公開資料整理編寫,非官方內容,僅供學習交流參考;軟體版權歸原作者所有,請支持正版;使用過程中遇到問題請查閱官方管道,本文不承擔任何責任。