<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>Fake on Tarragon</title><link>https://tarrragon.github.io/blog/tags/fake/</link><description>Recent content in Fake on Tarragon</description><generator>Hugo -- gohugo.io</generator><language>zh-TW</language><copyright>Tarragon (CC BY 4.0)</copyright><lastBuildDate>Mon, 20 Jul 2026 00:00:00 +0800</lastBuildDate><atom:link href="https://tarrragon.github.io/blog/tags/fake/index.xml" rel="self" type="application/rss+xml"/><item><title>Test Double Taxonomy（Fowler 分類）</title><link>https://tarrragon.github.io/blog/testing/knowledge-cards/test-double-taxonomy/</link><pubDate>Mon, 20 Jul 2026 00:00:00 +0800</pubDate><guid>https://tarrragon.github.io/blog/testing/knowledge-cards/test-double-taxonomy/</guid><description>&lt;p>Test double 是所有「用來取代真實依賴」的測試替身的統稱，Martin Fowler 把它拆成五種角色：dummy（只填參數位置、從不被實際使用）、&lt;a href="https://tarrragon.github.io/blog/testing/knowledge-cards/stub/" data-link-title="Stub" data-link-desc="測試作者手動寫死回應資料的 test double：驗證的是假設成立時邏輯是否正確，假設本身錯誤時無法檢出">stub&lt;/a>（測試作者寫死固定回應）、spy（記錄呼叫過程、供事後檢查）、mock（預先設定期望、呼叫不符期望即失敗）、fake（有狀態、可運作的簡化實作）。五種角色的分野在「資料從哪裡來」與「驗證的是狀態還是互動」，不是隨口互換的同義詞。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>本模組已經在用三種角色、只是沒有集中命名：&lt;a href="https://tarrragon.github.io/blog/testing/knowledge-cards/mock-masking/" data-link-title="Mock Masking（Mock 遮蔽）" data-link-desc="mock 模擬 API 層但不模擬協議層，造成的結構性驗證盲區">mock 遮蔽&lt;/a>討論的 mock，忠實模擬 API 層的方法簽名與參數型別，驗證呼叫是否符合預期介面；&lt;a href="https://tarrragon.github.io/blog/testing/knowledge-cards/stub/" data-link-title="Stub" data-link-desc="測試作者手動寫死回應資料的 test double：驗證的是假設成立時邏輯是否正確，假設本身錯誤時無法檢出">stub&lt;/a>是測試作者逐條寫死的固定回應，驗證「假設成立時」邏輯是否正確；&lt;a href="https://tarrragon.github.io/blog/testing/knowledge-cards/semantic-fake-backend/" data-link-title="Semantic Fake Backend（語意級假後端）" data-link-desc="持有狀態、只固化已證實後端行為的測試假件；與由測試餵資料的 stub 以狀態歸屬和行為出處劃界">語意級假後端&lt;/a>對應 fake——有狀態、可運作、模擬已證實後端行為的簡化實作。三者的差異不是實作細節，是各自能檢出的 bug 類型不同：mock 檢出介面誤用，stub 檢不出假設本身的錯誤，fake 能讓假設在多服務接力中被真正驗證。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>判斷一段程式碼裡的替身屬於哪個角色，看兩件事：資料是不是每條測試手動寫死的（是 → stub 或 dummy，取決於有沒有被實際讀取）、驗證是斷言最終狀態還是斷言呼叫發生過（前者偏 stub/fake，後者偏 spy/mock）。混用角色而不自知的訊號是：團隊說「這裡有 mock」，但程式碼裡是逐條寫死回應、沒有設定呼叫期望——用詞是 mock、行為是 stub，兩者的可測範圍不同，混用會讓覆蓋率的認知跟實際脫節。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>選角色的判準是「要驗證什麼」：只驗證程式碼內部邏輯、不涉及外部行為假設 → stub 或 dummy 就夠；要驗證「呼叫方式是否符合介面契約」→ mock；要驗證「假設成立時的多服務接力行為」，且假設本身有實測出處 → fake。角色選錯的典型後果是&lt;a href="https://tarrragon.github.io/blog/testing/knowledge-cards/frozen-vs-live-reference/" data-link-title="Frozen vs Live Reference（凍結參照與活解析）" data-link-desc="下游持有上游 id 的兩種策略——寫死 id vs 查詢時動態解引用；上游重建後凍結參照失效，stub 對此結構性盲目">凍結參照與活解析&lt;/a>描述的那類盲區——用 stub 的地方假設會變、卻用了固定回應，狀態變化不會在測試裡發生。跨層盲區（協議層、假設層）疊加時，測試綠燈能證明的範圍比表面上薄。&lt;/p></description><content:encoded><![CDATA[<p>Test double 是所有「用來取代真實依賴」的測試替身的統稱，Martin Fowler 把它拆成五種角色：dummy（只填參數位置、從不被實際使用）、<a href="/blog/testing/knowledge-cards/stub/" data-link-title="Stub" data-link-desc="測試作者手動寫死回應資料的 test double：驗證的是假設成立時邏輯是否正確，假設本身錯誤時無法檢出">stub</a>（測試作者寫死固定回應）、spy（記錄呼叫過程、供事後檢查）、mock（預先設定期望、呼叫不符期望即失敗）、fake（有狀態、可運作的簡化實作）。五種角色的分野在「資料從哪裡來」與「驗證的是狀態還是互動」，不是隨口互換的同義詞。</p>
<h2 id="概念位置">概念位置</h2>
<p>本模組已經在用三種角色、只是沒有集中命名：<a href="/blog/testing/knowledge-cards/mock-masking/" data-link-title="Mock Masking（Mock 遮蔽）" data-link-desc="mock 模擬 API 層但不模擬協議層，造成的結構性驗證盲區">mock 遮蔽</a>討論的 mock，忠實模擬 API 層的方法簽名與參數型別，驗證呼叫是否符合預期介面；<a href="/blog/testing/knowledge-cards/stub/" data-link-title="Stub" data-link-desc="測試作者手動寫死回應資料的 test double：驗證的是假設成立時邏輯是否正確，假設本身錯誤時無法檢出">stub</a>是測試作者逐條寫死的固定回應，驗證「假設成立時」邏輯是否正確；<a href="/blog/testing/knowledge-cards/semantic-fake-backend/" data-link-title="Semantic Fake Backend（語意級假後端）" data-link-desc="持有狀態、只固化已證實後端行為的測試假件；與由測試餵資料的 stub 以狀態歸屬和行為出處劃界">語意級假後端</a>對應 fake——有狀態、可運作、模擬已證實後端行為的簡化實作。三者的差異不是實作細節，是各自能檢出的 bug 類型不同：mock 檢出介面誤用，stub 檢不出假設本身的錯誤，fake 能讓假設在多服務接力中被真正驗證。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>判斷一段程式碼裡的替身屬於哪個角色，看兩件事：資料是不是每條測試手動寫死的（是 → stub 或 dummy，取決於有沒有被實際讀取）、驗證是斷言最終狀態還是斷言呼叫發生過（前者偏 stub/fake，後者偏 spy/mock）。混用角色而不自知的訊號是：團隊說「這裡有 mock」，但程式碼裡是逐條寫死回應、沒有設定呼叫期望——用詞是 mock、行為是 stub，兩者的可測範圍不同，混用會讓覆蓋率的認知跟實際脫節。</p>
<h2 id="設計責任">設計責任</h2>
<p>選角色的判準是「要驗證什麼」：只驗證程式碼內部邏輯、不涉及外部行為假設 → stub 或 dummy 就夠；要驗證「呼叫方式是否符合介面契約」→ mock；要驗證「假設成立時的多服務接力行為」，且假設本身有實測出處 → fake。角色選錯的典型後果是<a href="/blog/testing/knowledge-cards/frozen-vs-live-reference/" data-link-title="Frozen vs Live Reference（凍結參照與活解析）" data-link-desc="下游持有上游 id 的兩種策略——寫死 id vs 查詢時動態解引用；上游重建後凍結參照失效，stub 對此結構性盲目">凍結參照與活解析</a>描述的那類盲區——用 stub 的地方假設會變、卻用了固定回應，狀態變化不會在測試裡發生。跨層盲區（協議層、假設層）疊加時，測試綠燈能證明的範圍比表面上薄。</p>
]]></content:encoded></item></channel></rss>