"Mock"
- Mock 邊界判斷決策表
什麼時候 mock 夠用、什麼時候需要真實服務 — 從 API 層 / 協議層 / 環境層的斷裂點判斷 mock 的適用範圍
- T.C1 WebSocket text/binary frame 被 FakeWebSocketChannel 遮蔽
Flutter app 用 Uint8List 發送 WS 資料走 binary frame,ttyd 期望 text frame 靜默忽略 — FakeWebSocketChannel 的 sink.add 接受 dynamic 不區分 frame type,192 個 test 全過但實機無回應
- 三層定義與職責表
Unit Test / Protocol Integration Test / Screen State Test 各層職責、驗證目標與盲區的完整論述
- Mock Masking(Mock 遮蔽)
mock 模擬 API 層但不模擬協議層,造成的結構性驗證盲區
- Mock 遮蔽機制分析
Mock 在 API 層、協議層、環境層之間製造的結構性盲區 — 斷裂點在哪、為什麼 mock 無法也不應該模擬協議行為
- T.C2 Auth handshake 邏輯缺失被 FakeWebSocketChannel 遮蔽
ttyd 連線後需要發送 auth token JSON frame 完成認證,整個邏輯未實作 — FakeWebSocketChannel 的 ready 立即完成不需認證,test 永遠看到連線成功
- 「名義 integration test」的識別與修正
test 名稱含 integration 但核心依賴全用 fake — 如何辨認、為什麼有害、怎麼修正命名和測試策略
- 判斷原則:什麼時候需要 protocol integration test
從服務架構特徵判斷是否需要 protocol integration test 的決策流程 — 協議複雜度、mock 寬鬆度、失敗靜默度三個維度
- 反模式:用 mock 數量彌補 mock 盲區
為什麼增加 mock test 數量無法跨越 mock 的結構性盲區 — 從 192 個 test 全過的案例拆解數量與覆蓋率的真正關係
- Test Double Taxonomy(Fowler 分類)
test double 依據回應資料的來源與驗證方式分成五種角色,各自對應不同的可測範圍與盲區
- 1101 行自建測試基礎設施、重構刪掉 82.5% — 過度工程的三種形態
自建測試基礎設施前先問框架的標準做法是什麼:mock 純資料物件、helper 帶並發鎖與記憶體洩漏防護、mock 放進 lib/ 進生產依賴圖,三種形態都在重新發明 Riverpod overrideWith 一行就有的東西。精緻的設計文件不是價值證明——它可以精心規劃一個不需要存在的系統。
- mock 要配置 55 個方法、實際只用 5 個 — 測試痛是介面設計痛的探針
service 測試的 mock 負擔正比於它依賴的介面寬度:依賴四個大介面共 55 個方法、實際呼叫 5 個,91% 的 mock 配置是純浪費、還會炸 MissingStubError。修法是介面隔離——抽出只含實際使用方法的 Port,讓 mock 縮到跟真實依賴一樣窄;為未來預留的方法用 TODO 標記啟用時機。
- 產品碼自己是 mock — ViewModel 假實作通過了 15 個測試
ViewModel 用 Future.delayed 加硬編碼資料交付、狀態轉換測試全綠,因為測試耦合的是狀態機、不是業務效果。假實作被當成完成的基礎,直到 63 個測試「寫不出來」才現形——測試的可寫性是實作真實性的探針。
- 測「不變」、不測「正確」 — characterization test 當遷移安全網
大規模型別遷移前,對著舊實作寫一批鎖住現有行為的測試——包括看起來像 bug 的邊界怪癖也照鎖,遷移後全綠證明「換底沒改行為」。正確性是另一批測試的職責、混在一起紅燈就無法歸因。附測試環境的原生依賴三個斷點(FFI、plugin、late init)與替身解法。
- 192 個測試全過、實機全壞:Mock 遮蔽真實行為的三層測試策略
unit test 全綠、實機部署後功能整片壞掉。mock-only 策略的結構盲區(text vs binary frame、缺 auth handshake、ANSI 多樣性被 FakeWebSocketChannel 遮蔽),以及分層測試各抓什麼、各遮蔽什麼。