Skip to main content

為何要使用 Mock

在撰寫測試時,會有一些實際上不希望執行的處理,例如寄信、快取讀寫或呼叫外部 API。 把這類處理替換為「假裝的替身」的作法就稱為 mock。 Mock 的好處包含:
  • 測試速度快:不執行外部服務或耗時處理,測試很快完成
  • 測試穩定:不受外部服務狀態影響,結果始終一致
  • 測試範圍清晰:可以只驗證單一類別或方法
Laravel 已提供可立即使用的 mock 輔助函式,涵蓋事件、Job、Facade 等。 其內部使用 Mockery,不需複雜設定即可使用。

Mock 物件

若要 mock 透過服務容器注入的物件,可將 mock 實例綁定到容器。 如此一來,容器會用 mock 實例取代原本要建立的物件。

mock() 方法

Laravel 測試基底類別提供的 mock() 方法可以更精簡地寫出同樣結果。

partialMock() 方法

若只想 mock 物件的部分方法,可用 partialMock()。 未 mock 的方法會照常執行。

spy() 方法

Spy 類似 mock,但差在執行程式碼後才驗證互動。 Mock 是事先設定「這個方法應該被呼叫」;spy 則是事後檢查「這個方法是否有被呼叫」。

Facade 的 Mock

Facade 與一般靜態方法呼叫不同,是可以 mock 的。 在具備依賴注入等同可測試性的同時,可用更簡潔的語法書寫。 以使用快取的控制器為例:
要 mock Cache Facade 的 get 方法,使用 expects()
請不要 mock Request Facade。改為在 getpost 等 HTTP 測試方法上傳入輸入資料。同樣地,別 mock Config Facade,改在測試中直接呼叫 Config::set()

Facade Spy

要以 spy 監控 Facade,可呼叫對應 Facade 的 spy() 方法。 適合在程式碼執行後才驗證互動的情境。

時間操作

在測試中驗證與時間相依的邏輯時,能改變 now()Carbon::now() 所回傳的時間會很方便。 Laravel 的 feature test 基底類別提供了操作時間的輔助方法。

travel() — 移動時間

用閉包做時間移動

傳入閉包給時間移動方法時,會在指定時間停止時間並執行閉包,完成後恢復到原本時間。

freezeTime() — 停止時間

freezeTime() 會凍結目前時間。freezeSecond() 會凍結在目前秒的起點。

實用範例:閒置討論串的鎖定

時間操作非常適合測試如「一段時間無操作即鎖定討論串」這類功能。
travel() 等時間操作方法只能在 feature 測試(繼承 Tests\TestCase 的類別)中使用,PHPUnit 的基底 TestCase 中無法使用。

方法一覽

Mock 相關

時間操作相關

最後修改於 2026年8月2日