Spring Boot 06:測試到底證明什麼?從除錯走到 JAR/WAR
mvn test 顯示綠燈,你應該更相信哪些事情?如果回答是「整個系統都沒問題」,就把測試的範圍想得太大了。這一課從實際 assertion 往回讀,再看同一份程式換成不同啟動方式後,還欠哪些驗證。
先知道測試建立了什麼環境
@SpringBootTest(properties = {
"spring.datasource.url=jdbc:h2:mem:bootlab-test;DB_CLOSE_DELAY=-1",
"lab.label=test-label"
})
@AutoConfigureMockMvc
class LabIntegrationTest {
// See the download for injected fields and complete tests.
}@SpringBootTest 載入應用 context;本例搭配 MockMvc,在程序內走 MVC 請求處理,不等於真的打開 TCP port。它使用真實的 Service 與 H2 JDBC,不是把整條鏈都 mock 掉。這個測試因此能觀察資料寫入,但仍不能證明 EAP、DB2 或 MQ 的整合。
| 方式 | 適合確認 | 仍未涵蓋 |
|---|---|---|
| 普通單元測試 | 一個函式或類別的規則 | Spring wiring 與交易代理 |
| MVC slice,例如 @WebMvcTest | HTTP mapping、轉換與驗證 | 真實 DB/整個應用 context |
| 本例 context+MockMvc+H2 | 這組 HTTP 與資料副作用 | 真實 TCP、DB2、EAP、MQ |
| 打包 JAR+實際 HTTP | 打包後可啟動、內嵌伺服器回應 | 外部容器模組與企業連線 |
| 目標環境同案例比對 | 實際整合與舊新行為 | 未測的案例與正式流量 |
讀 assertion,別只讀測試名稱
mvc.perform(post("/api/tickets")
.contentType("application/json")
.content("{\"title\":\" \"}"))
.andExpect(status().isBadRequest())
.andExpect(jsonPath("$.code").value("INVALID_REQUEST"));
assertThat(count()).isZero();這段擷取自空白標題案例。它同時看 400、錯誤 code 與沒有資料寫入,避免出現「回應拒絕了,資料卻留下來」的落差。新增成功的案例另比對 201、Location、回傳 id 與再次查詢結果。動態 id 不直接比固定字串,要驗證它在回應、Location 與查詢之間的關聯。
範例含八個整合測試,詳細執行證據見下載檔 VALIDATION.md。這不是 coverage 百分比,也不是對所有輸入的保證。若改了日期、權限或重試語意,就需要新增對應案例;既有八個測試不會自動知道新風險。
除錯時先固定案例與版本
先記錄輸入、設定、產物版本、HTTP 回應與資料結果,再定位最早不符合預期的邊界。讀 stack trace 時,從最內層相關的 caused by 找原因;不要把最外層的「context 啟動失敗」當成真正問題。修改一個原因後重跑同一案例,才知道是哪個改動讓結果改變。
mvn test
mvn package
java -jar target/boot-learning-lab-1.0.0.jar --server.port=8081
# Another terminal:
curl -i http://127.0.0.1:8081/api/pingJAR 與 WAR:換的是部分執行責任
這個專案產出可執行 JAR,由 main 啟動內嵌伺服器。傳統 WAR 交給外部 Servlet 容器載入;Boot 官方做法包含 SpringBootServletInitializer、war packaging 與 provided 的容器依賴。不能只把副檔名改成 .war。下載檔刻意只提供 JAR,尚未實作或測試 EAP 的 WAR 版本。
到 EAP 後,先確認 listener 與 context root,再核對 DataSource/JNDI、交易管理者、logging 與實際載入的函式庫。server.port 不會替你改 EAP listener。Boot 3.5 傳統部署的 Servlet 條件只是其中一層,供應商支援矩陣與應用模組仍須獨立確認。
動手:寫一張自己接得住的交接卡
假設把 lab.max-title-length 從 80 改為 100。先預測哪個既有測試會失敗、資料表是否還裝得下,再寫交接:前後行為、設定位置、測試修改、仍未驗證的系統。不要只寫「調整設定,測試通過」。
答案:81 字元案例要改,但不能只刪 assertion
原本 81 個 ASCII 字元預期 422,現在應接受;需要補上 100 可接受、101 拒絕的邊界,並維持失敗沒有寫入的檢查。資料表上限 200 尚未被碰到,但舊系統契約若只允許 80,這仍是一個需要確認的行為變更。完成課程的標準,是你能把這個改動的理由、程式與證據連在一起。
搭配閱讀:整體升級責任圖下載本系列完整工單 API 範例(ZIP)