單元測試(Unit Test)是一段程式呼叫一個工作單元,並驗證這個工作單元的一個具體最終結果——如果對這個最終結果的假設是錯誤的,單元測試就失敗了。這篇文章整理單元測試的基礎觀念:什麼是工作單元與 SUT、優秀單元測試該有哪些特質、單元測試與整合測試怎麼分,以及 Arrange-Act-Assert 三步驟與 `TestCase`、Setup/Teardown 的實際用法。
什麼是單元測試?什麼是工作單元?
一個「單元」代表的是系統中的工作單元,或是一個使用案例。被測試的系統(System Under Test)我們稱做 SUT,或稱 Class Under Test(CUT)。
一個單元測試的範圍可以小到一個方法,大到多個類別。重點是:測試會呼叫這個工作單元,然後驗證它的一個具體最終結果,結果不如預期就判定測試失敗。
優秀單元測試有哪些特質?
一段好的單元測試應該同時具備以下特質:
- 自動化,可被重複執行
- 很容易被實現
- 非臨時性的(不是寫一次就丟的驗證腳本)
- 任何人都可以按一個按鈕就執行它
- 執行速度快
- 執行結果每次都是一致的
- 能完全掌控被測試的單元
- 完全被隔離的
- 若執行失敗,會有清楚的原因
單元測試和整合測試差在哪裡?
整合測試是一個有順序的測試過程,將軟硬體相結合並進行測試,直到整個系統被整合在一起。也就是說,整合測試對被測試的單元並沒有完全的控制,而是使用該單元一個或多個真實的相依物件,例如:時間、網路、資料庫、執行緒、亂數產生器等等。
簡單比較:
| 單元測試 | 整合測試 | |
|---|---|---|
| 相依物件 | 完全隔離、可控(可用 Fake Object 取代) | 使用真實相依物件(時間、網路、資料庫…) |
| 範圍 | 一個方法到多個類別 | 整個系統的整合 |
| 失敗原因定位 | 清楚、明確 | 可能來自任一整合環節 |
一個單元測試的三個行為:Arrange、Act、Assert
一個單元測試通常包含三個行為(又稱 AAA 模式):
- 準備(Arrange):建立物件,進行必要的設定
- 操作(Act):呼叫被測試物件的方法
- 驗證(Assert):驗證某件事符合預期
常見的 Assert 類別方法有:
- `Assert.True`:驗證一個布林條件(對應 `Assert.False`)
- `Assert.AreEqual`:驗證傳回的值應相同
- `Assert.AreSame`:驗證兩個參數應指向同一個物件
如何使用參數來測試(TestCase)?
當同一段邏輯要用多組輸入值反覆驗證時,可以使用 `TestCase` 標籤,把多組參數寫在同一個測試上,避免為每組資料複製貼上一個新測試方法:

測試執行時,每一組參數都會被當成獨立的案例執行與驗證:

Setup 和 Teardown 是做什麼的?
當多個測試都需要相同的初始化與清理工作時,可以把共用邏輯放到 Setup 與 Teardown:Setup 在每個測試執行前呼叫,Teardown 在每個測試結束後呼叫,讓每個測試都在乾淨、一致的狀態下執行:

延伸閱讀
- Socket.IO probe transport websocket failed:原因與 Cookie 分流解法
- 使用 Charles Proxy 抓取 Node.js 網路請求:Reverse Proxy 設定教學
- Node.js 伺服器管理工具 PM2:常用指令與設定教學
常見問題
單元測試的「單元」可以多大?
可以小到一個方法,大到多個類別,重點是它是一個明確的工作單元或使用案例,而且測試能驗證它的一個具體最終結果。
單元測試和整合測試怎麼選?
兩者都要有。單元測試負責快速驗證隔離後的邏輯,整合測試負責驗證單元與真實相依物件(資料庫、網路等)整合後的行為。
為什麼單元測試要求「完全被隔離」?
因為只有隔離了時間、網路、資料庫等相依物件,測試結果才會每次一致、執行速度才會快,失敗時也才能明確指出原因出在被測試的單元本身。
AAA(Arrange-Act-Assert)是什麼?
撰寫測試的三段式結構:先準備(Arrange)物件與設定,再操作(Act)呼叫被測試的方法,最後驗證(Assert)結果符合預期。
TestCase 標籤有什麼好處?
可以用參數化的方式,讓同一個測試方法跑多組輸入資料,避免為每一組資料複製一個幾乎相同的測試方法。
參考資料
- 收錄於 IT 邦幫忙鐵人賽系列文章(單元測試的藝術系列)
最後更新
2026-08-28(原文發布於 2018-07-27,本文保留原始筆記內容並補上 GEO 結構。)
關於作者 {#author}
Claire Chang | 企業 AI 導入與流程轉型顧問。專注於 AI Agent 架構設計、ERP 系統整合與企業 AI 治理。
首次發布:2018-07-27
