首頁 web前端 js教程 從 Fetch Mocks 到 MSW:測試之旅

從 Fetch Mocks 到 MSW:測試之旅

Dec 03, 2024 am 11:47 AM

From Fetch Mocks to MSW: A Testing Journey

催化劑:無辜的 Axios 重構

一切的開始都很天真。 「我將重構這些 fetch 呼叫以使用 Axios,」我想,「可能會出現什麼問題?」事實證明,相當多 - 具體來說,我所有精心製作的 fetch 模擬突然變得像巧克力茶壺一樣有用。

我決定利用這個機會來現代化我的方法,而不是為 Axios 重建所有模擬。輸入模擬服務人員 (MSW)。

老方法:玩笑嘲笑和獲取

以前,我的測試看起來像這樣:

const mockFetch = vi.fn();
global.fetch = mockFetch;

describe("API functions", () => {
  beforeEach(() => {
    mockFetch.mockReset();
  });

  test("fetchTrips - should fetch trips successfully", async () => {
    const mockTrips = [{ id: 1, name: "Trip to Paris" }];
    mockFetch.mockResolvedValueOnce({
      ok: true,
      json: async () => mockTrips,
    });

    const trips = await fetchTrips(mockSupabase);
    expect(trips).toEqual(mockTrips);
  });
});
登入後複製
登入後複製

它有效,但不夠優雅。每個測試都需要手動模擬設置,模擬很脆弱,它們並不能真正代表我的 API 在現實世界中的行為。我正在測試實作細節而不是實際行為。

輸入 MSW:更好的模擬方法

Mock Service Worker (MSW) 採用完全不同的 API 模擬方法。它不是模擬函數調用,而是在網路層級攔截實際的網路請求。由於以下幾個原因,這是巨大的:

  • 執行階段整合:MSW 透過攔截實際的 HTTP 請求來運作,這表示您的程式碼運作方式與生產環境中的運作方式完全相同。不再需要模擬 fetch 或 axios - 您的實際 API 呼叫運行不變。
  • API 優先設計:您無需考慮函數模擬,而是定義反映真實 API 的模擬 API 端點。這將推動您實現更好的 API 設計,並使您的測試與實際端點保持一致。
  • 請求/回應保真度:您可以使用真正的 HTTP 概念 - 狀態碼、標頭、回應正文 - 而不是簡化的模擬物件。這意味著您可以捕獲更現實的邊緣情況。

以下是使用 MSW 進行相同測試的結果:

// Your API handler definition
http.get(`${BASE_URL}/trips`, () => {
  return HttpResponse.json([
    { id: "1", location: "Trip 1", days: 5, startDate: "2023-06-01" },
    { id: "2", location: "Trip 2", days: 7, startDate: "2023-07-15" },
  ]);
});

// Your test - notice how much cleaner it is
test("fetchTrips - should fetch trips successfully", async () => {
  const trips = await fetchTrips();
  expect(trips).toEqual([
    { id: "1", location: "Trip 1", days: 5, startDate: "2023-06-01" },
    { id: "2", location: "Trip 2", days: 7, startDate: "2023-07-15" },
  ]);
});
登入後複製
登入後複製

每個測試不再需要手動模擬設定 - MSW 處理程序會處理這一切。另外,這些處理程序可以在許多測試中重複使用,減少重複並使您的測試更易於維護。

設定

設置城市固體廢棄物非常簡單,這立即讓我產生了懷疑。測驗中沒有什麼是那麼容易的...

beforeAll(() => {
  server.listen({ onUnhandledRequest: "bypass" });
});

afterEach(() => {
  server.resetHandlers();
  cleanup();
});

afterAll(() => {
  server.close();
});
登入後複製

然後建立實際上看起來像我的 API 的處理程序:

export const handlers = [
  http.get(`${BASE_URL}/trips`, () => {
    return HttpResponse.json([
      { id: "1", location: "Trip 1", days: 5, startDate: "2023-06-01" },
      { id: "2", location: "Trip 2", days: 7, startDate: "2023-07-15" },
    ]);
  }),
];
登入後複製

錯誤處理之旅

我第一次嘗試錯誤處理......好吧,我們可以說它是樂觀的:

export const errorHandlers = [
  http.get(`${BASE_URL}/trips/999`, () => {
    return new HttpResponse(null, { status: 404 });
  }),
];
登入後複製

問題?更通用的 /trips/:id 處理程序首先捕獲所有內容。這就像在 Express 應用程式中在特定路線之前有一條包羅萬象的路線 - 菜鳥錯誤。

經過一些令人頭痛的測試失敗後,我意識到更好的方法是處理路由本身的錯誤:

const mockFetch = vi.fn();
global.fetch = mockFetch;

describe("API functions", () => {
  beforeEach(() => {
    mockFetch.mockReset();
  });

  test("fetchTrips - should fetch trips successfully", async () => {
    const mockTrips = [{ id: 1, name: "Trip to Paris" }];
    mockFetch.mockResolvedValueOnce({
      ok: true,
      json: async () => mockTrips,
    });

    const trips = await fetchTrips(mockSupabase);
    expect(trips).toEqual(mockTrips);
  });
});
登入後複製
登入後複製

這種模式出現了:我可以在同一個地方處理成功和錯誤情況,而不是單獨的錯誤處理程序,就像真正的 API 一樣。這是“啊哈!”之一。測試實際上推動您走向更好的設計的時刻。

經驗教訓

  1. 在正確的級別進行模擬:MSW 可以讓您模擬網路級別而不是功能級別,從而使測試更加真實和穩健。
  2. 思考端點,而不是函數:圍繞 API 端點建立模擬,而不是單一函數調用,可以更好地代表實際的應用程式行為。
  3. 在發生錯誤時進行處理:無需使用單獨的錯誤處理程序,而是在端點處理程序本身內處理錯誤 - 就像真正的 API 一樣。

最終結果

最終的設定更易於維護,更現實,並且實際上有助於捕捉真正的問題。的日子已經一去不復返了:

// Your API handler definition
http.get(`${BASE_URL}/trips`, () => {
  return HttpResponse.json([
    { id: "1", location: "Trip 1", days: 5, startDate: "2023-06-01" },
    { id: "2", location: "Trip 2", days: 7, startDate: "2023-07-15" },
  ]);
});

// Your test - notice how much cleaner it is
test("fetchTrips - should fetch trips successfully", async () => {
  const trips = await fetchTrips();
  expect(trips).toEqual([
    { id: "1", location: "Trip 1", days: 5, startDate: "2023-06-01" },
    { id: "2", location: "Trip 2", days: 7, startDate: "2023-07-15" },
  ]);
});
登入後複製
登入後複製

相反,我有適當的 API 模擬:

  • 處理成功與錯誤狀況
  • 使用現實的反應結構
  • 可以在測試中重複使用
  • 實際擷取整合問題

接下來是什麼?

展望未來,我很興奮:

  • 更真實地模擬網路錯誤
  • 使用 MSW 的瀏覽器整合進行端對端測試
  • 新增回應延遲來測試載入狀態

有時最好的改進來自於被迫改變。最初的簡單 Axios 重構最終導致了更好的測試架構。這不就是重構的意義嗎?


這篇文章最初發表在我的部落格上。追蹤我,了解更多有關全端開發、測試和 API 設計的內容。

以上是從 Fetch Mocks 到 MSW:測試之旅的詳細內容。更多資訊請關注PHP中文網其他相關文章!

本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

Video Face Swap

Video Face Swap

使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱門文章

<🎜>:泡泡膠模擬器無窮大 - 如何獲取和使用皇家鑰匙
4 週前 By 尊渡假赌尊渡假赌尊渡假赌
北端:融合系統,解釋
4 週前 By 尊渡假赌尊渡假赌尊渡假赌
Mandragora:巫婆樹的耳語 - 如何解鎖抓鉤
3 週前 By 尊渡假赌尊渡假赌尊渡假赌

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發工具

SublimeText3 Mac版

SublimeText3 Mac版

神級程式碼編輯軟體(SublimeText3)

熱門話題

Java教學
1671
14
CakePHP 教程
1428
52
Laravel 教程
1331
25
PHP教程
1276
29
C# 教程
1256
24
Python vs. JavaScript:學習曲線和易用性 Python vs. JavaScript:學習曲線和易用性 Apr 16, 2025 am 12:12 AM

Python更適合初學者,學習曲線平緩,語法簡潔;JavaScript適合前端開發,學習曲線較陡,語法靈活。 1.Python語法直觀,適用於數據科學和後端開發。 2.JavaScript靈活,廣泛用於前端和服務器端編程。

從C/C到JavaScript:所有工作方式 從C/C到JavaScript:所有工作方式 Apr 14, 2025 am 12:05 AM

從C/C 轉向JavaScript需要適應動態類型、垃圾回收和異步編程等特點。 1)C/C 是靜態類型語言,需手動管理內存,而JavaScript是動態類型,垃圾回收自動處理。 2)C/C 需編譯成機器碼,JavaScript則為解釋型語言。 3)JavaScript引入閉包、原型鍊和Promise等概念,增強了靈活性和異步編程能力。

JavaScript和Web:核心功能和用例 JavaScript和Web:核心功能和用例 Apr 18, 2025 am 12:19 AM

JavaScript在Web開發中的主要用途包括客戶端交互、表單驗證和異步通信。 1)通過DOM操作實現動態內容更新和用戶交互;2)在用戶提交數據前進行客戶端驗證,提高用戶體驗;3)通過AJAX技術實現與服務器的無刷新通信。

JavaScript在行動中:現實世界中的示例和項目 JavaScript在行動中:現實世界中的示例和項目 Apr 19, 2025 am 12:13 AM

JavaScript在現實世界中的應用包括前端和後端開發。 1)通過構建TODO列表應用展示前端應用,涉及DOM操作和事件處理。 2)通過Node.js和Express構建RESTfulAPI展示後端應用。

了解JavaScript引擎:實施詳細信息 了解JavaScript引擎:實施詳細信息 Apr 17, 2025 am 12:05 AM

理解JavaScript引擎內部工作原理對開發者重要,因為它能幫助編寫更高效的代碼並理解性能瓶頸和優化策略。 1)引擎的工作流程包括解析、編譯和執行三個階段;2)執行過程中,引擎會進行動態優化,如內聯緩存和隱藏類;3)最佳實踐包括避免全局變量、優化循環、使用const和let,以及避免過度使用閉包。

Python vs. JavaScript:社區,圖書館和資源 Python vs. JavaScript:社區,圖書館和資源 Apr 15, 2025 am 12:16 AM

Python和JavaScript在社區、庫和資源方面的對比各有優劣。 1)Python社區友好,適合初學者,但前端開發資源不如JavaScript豐富。 2)Python在數據科學和機器學習庫方面強大,JavaScript則在前端開發庫和框架上更勝一籌。 3)兩者的學習資源都豐富,但Python適合從官方文檔開始,JavaScript則以MDNWebDocs為佳。選擇應基於項目需求和個人興趣。

Python vs. JavaScript:開發環境和工具 Python vs. JavaScript:開發環境和工具 Apr 26, 2025 am 12:09 AM

Python和JavaScript在開發環境上的選擇都很重要。 1)Python的開發環境包括PyCharm、JupyterNotebook和Anaconda,適合數據科學和快速原型開發。 2)JavaScript的開發環境包括Node.js、VSCode和Webpack,適用於前端和後端開發。根據項目需求選擇合適的工具可以提高開發效率和項目成功率。

C/C在JavaScript口譯員和編譯器中的作用 C/C在JavaScript口譯員和編譯器中的作用 Apr 20, 2025 am 12:01 AM

C和C 在JavaScript引擎中扮演了至关重要的角色,主要用于实现解释器和JIT编译器。1)C 用于解析JavaScript源码并生成抽象语法树。2)C 负责生成和执行字节码。3)C 实现JIT编译器,在运行时优化和编译热点代码,显著提高JavaScript的执行效率。

See all articles