在 SSR 中模擬 Next-Auth 以進行 E2E 測試

Next.js 是一個支援伺服器端渲染 (SSR) 的框架。在實作中通常採用混合方式—應用程式的某些部分依賴於 SSR 傳遞資料,而其他部分則使用客戶端渲染 (CSR)。然而,目前針對 next-auth 的端到端 (E2E) 測試設定僅涵蓋 CSR 的情境。本文目的為試圖擴展測試的範圍,使其也能支援 SSR,同時具備根據不同條件動態配置的彈性。為了實現這一目標,SSR 和 CSR 都必須能支援模擬身分驗證,否則在測試期間將不得不完全忽略身分驗證。

也就是說,我們的目的是…

預期會希望能產出類似 Vitest 或 Jest 的 vi.fnvi.mockvi.spyOn 來模擬 getServerSession 的功能,這樣就能在測試期間模擬 getServerSession 的行為,並根據不同的情境回應相應的 session 資料。

關於解法以下是一些提案。

解法 1:使用 next-auth-mock

next-auth-mock 是專為使用 Vitest 或 Jest 進行單元測試設計的工具。它透過在 Node.js 環境中模擬 session object 來運作。然而,由於 E2E 框架在進行測試時是在瀏覽器層級操作,next-auth-mock 無法在此情境中使用。建議參考解法 2 可能會是更適合的方法。

解法 2:使用 CredentialsProvider 模擬身分驗證

CredentialsProvider 取代 Google auth 或 Keycloak 機制,並僅在測試環境中使用。注意,使用環境變數來判定是否啟用這個假的 CredentialsProvider

非 auth 相關的其他 API 回應也可透過專為測試環境設計的 mockApiProvider 來模擬,從而自動模擬 API 回應。要注意的是,頁面層級的路由如 Playwright 的 page.route 僅適用於 CSR,不能用來模擬 SSR 階段的 API 呼叫。SSR 的 getServerSideProps 的操作是在伺服器端執行,而這些 E2E 框架的測試則是模擬客戶端/瀏覽器端的互動。因此,page.route 無法攔截 SSR 階段的 API 呼叫。 若要在僅限測試的環境中實現 SSR 回應模擬,建議使用環境變數結合專為測試設計的模擬模組,在測試環境中啟用 SSR 模擬,同時保持 production 環境不受影響。

如何根據不同的使用情境調整測試資料,可以考慮以下幾種方式:

解法 3:透過 MSW 模擬 Session

如果不想透過 CredentialsProvider 模擬登入,可以考慮 (1) 使用 MSW 模擬 session 的 API 呼叫,它會回應一個固定的模擬 session 物件;或是 (2) 在 Node 環境中,直接用模擬物件替代由 getServerSession 回應的 session 物件。透過 MSW 模擬 session 的解法特別適合用於單元測試或整合測試。但要注意的是 MSW 會攔截 HTTP 請求,適用於 CSR,並且由於 session 的解析是在伺服器端進行,而非在客戶端或瀏覽器端完成,因此無法用於 SSR。

解法 4:跳過身分驗證流

如果上述方案均無法實現,可以考慮在測試過程中完全跳過身分驗證流程。幸運的是解法 2 是可行的,不需要跳過身分驗證的步驟,而能進行完整的 E2E 測試。

總結

以下是各種解法的對比表:

解法 適用情境 優點 缺點
解法 1:使用 next-auth-mock 單元測試 簡單易用, 快速模擬使用者狀態 僅限於單元測試, 不適用於端到端測試(E2E)
解法 2:使用 CredentialsProvider 端到端測試(CSR 和 SSR 渲染) 支援真實的身分驗證模擬, 同時適用於 CSR 和 SSR 渲染場景, 可利用環境變數彈性進行配置 需要額外設置, 注入測試資料更加複雜
解法 3:使用 MSW 模擬 session CSR 渲染 對 API 回應有高度控制, 適合前端測試 無法覆蓋 SSR 渲染, 需要額外的測試環境設置
解法 4:跳過身分驗證流程 基本功能測試 簡單快捷, 無需額外配置 無法測試身分驗證行為,` 不支援全面的端到端測試

跟預期不同的是,最後並沒有實現類似 Vitest 或 Jest 的 vi.fnvi.mockvi.spyOn 的功能來模擬 getServerSession。這是因為在 SSR 渲染階段,getServerSession 的行為是在伺服器端執行,而 E2E 測試框架通常是在客戶端/瀏覽器端進行操作。因此,無法直接在客戶端模擬伺服器端的行為。

推薦的解決方案是使用 CredentialsProvider 來模擬身分驗證,這樣就可以在 SSR 和 CSR 渲染中都能有效地支援測試。這種方法不僅能夠模擬身分驗證,還能根據不同的環境變數進行動態配置,進而提升測試的彈性。

參考資料


Next.js End-to-End Testing SSR CSR react.js Playwright front end testing node.js 單元測試 端對端測試 自動化測試