iT邦幫忙

2026 iThome 鐵人賽

DAY 23
0
Software Development

下載器不是寫完就能跑:一個 HLS 分段式串流工具的架構與測試修練系列 第 23 篇

Day 23:測試網路請求——手刻一個 async mock response,而不是真的發請求

  • 分享至 

  • xImage
  •  

前言:測試爬蟲邏輯,要真的發網路請求嗎?

如果測試每次都要真的對外發送請求,會有一連串問題:測試變慢、測試結果依賴外部服務是否正常運作、外部內容一旦改版測試就會莫名其妙失敗。要測試的是「解析邏輯對不對」,不是「網路連得通嗎」——這兩件事該用不同的方式驗證。

今日目標

  • 認識為什麼網路請求需要用測試替身(Test Double)取代
  • 看真實測試程式碼怎麼手刻一個符合非同步 HTTP 用戶端介面的假回應
  • 理解「介面吻合」是替身能不能用的關鍵

真實測試程式碼裡的手刻 mock

class MockResponse:
    def __init__(self, content: bytes, headers: dict):
        self._content = content
        self.headers = headers

    async def read(self):
        return self._content

    def raise_for_status(self):
        pass

    async def __aenter__(self):
        return self

    async def __aexit__(self, exc_type, exc, tb):
        pass

這個類別手刻了 async with 語法需要的 __aenter__/__aexit__,還有 HTTP client 常見介面裡的 read()、raise_for_status()——它不是在模擬「網路請求」這件事本身,而是在模擬「呼叫端實際會用到的那組介面」,讓被測試的程式碼以為自己在跟真實的 HTTP client 互動,實際上拿到的是完全可控的假資料。

用 get_fixture 依請求網址分派對應的假資料

def get_fixture(url: str) -> bytes:
    if 'source-a' in url:
        return read_file('fixtures/source-a/page.html')
    if 'source-b' in url:
        return read_file('fixtures/source-b/page.html')
    ...

@patch.object(Http, 'get')
async def test_collect_items(mock_get, mocker: MockFixture):
    mock_get.side_effect = lambda url: get_fixture(url)
    ...

這種設計讓測試碼可以針對「同一個爬蟲,面對不同網址該回傳什麼假資料」建立一份對照表,而不用為每個測試案例各自手刻一份 mock 設定——測試資料的組織方式,本身也是值得花心思設計的一環。

介面吻合,是替身能不能用的關鍵

手刻 mock 最容易犯的錯,是只模擬了「目前這段程式碼用到的方法」,漏掉了一些邊界情況會用到、但當下沒注意到的介面細節——例如某個呼叫路徑其實會呼叫 response.headers,但 mock 只實作了 read()。這種遺漏平常不會被發現,直到程式碼的某個分支第一次真的走到那條路徑,測試才會因為 AttributeError 失敗,而且失敗訊息通常不會直接告訴你「這是 mock 沒做完整」,需要一點除錯功夫才看得出來。

今日思考題

你測試過依賴外部 HTTP 呼叫的程式碼嗎?用的是手刻 mock、現成的 mock 函式庫,還是真的發請求打測試伺服器?手刻的 mock 有沒有涵蓋到你目前還沒踩到、但介面上其實存在的方法?

今日重點回顧

  • 測試解析邏輯不該依賴真實網路請求,會讓測試變慢、不穩定、依賴外部服務狀態
  • 手刻 mock 的關鍵是模擬「呼叫端實際會用到的介面」,不是模擬網路請求本身
  • 介面吻合是替身能不能用的關鍵,遺漏的介面細節通常要到對應分支被觸發才會曝光

明日預告

明天講測試檔案系統操作:用假的檔案系統,不用真的寫磁碟。


上一篇
Day 22:第三部回顧——下載引擎的失敗處理,是設計出來的,不是加出來的
系列文
下載器不是寫完就能跑:一個 HLS 分段式串流工具的架構與測試修練 共 23 篇
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言