摘要:測試調用斷言的執行后返回斷言被調用斷言被調用了一次斷言傳入的參數為所創建的函數還可以設置返回值,定義內部實現或返回對象。
在本篇教程中,我們會介紹 Jest 中的三個與 Mock 函數相關的API,分別是jest.fn()、jest.spyOn()、jest.mock()。使用它們創建Mock函數能夠幫助我們更好的測試項目中一些邏輯較復雜的代碼,例如測試函數的嵌套調用,回調函數的調用等。
如果你還不知道Jest的基本使用方法,請先閱讀: 《使用Jest測試JavaScript (入門篇)》為什么要使用Mock函數?
在項目中,一個模塊的方法內常常會去調用另外一個模塊的方法。在單元測試中,我們可能并不需要關心內部調用的方法的執行過程和結果,只想知道它是否被正確調用即可,甚至會指定該函數的返回值。此時,使用Mock函數是十分有必要。
Mock函數提供的以下三種特性,在我們寫測試代碼時十分有用:
捕獲函數調用情況
設置函數返回值
改變函數的內部實現
我們接著使用上篇文章中的目錄結構,在test/functions.test.js文件中編寫測試代碼,src/目錄下寫被測試代碼。1. jest.fn()
jest.fn()是創建Mock函數最簡單的方式,如果沒有定義函數內部的實現,jest.fn()會返回undefined作為返回值。
// functions.test.js test("測試jest.fn()調用", () => { let mockFn = jest.fn(); let result = mockFn(1, 2, 3); // 斷言mockFn的執行后返回undefined expect(result).toBeUndefined(); // 斷言mockFn被調用 expect(mockFn).toBeCalled(); // 斷言mockFn被調用了一次 expect(mockFn).toBeCalledTimes(1); // 斷言mockFn傳入的參數為1, 2, 3 expect(mockFn).toHaveBeenCalledWith(1, 2, 3); })
jest.fn()所創建的Mock函數還可以設置返回值,定義內部實現或返回Promise對象。
// functions.test.js test("測試jest.fn()返回固定值", () => { let mockFn = jest.fn().mockReturnValue("default"); // 斷言mockFn執行后返回值為default expect(mockFn()).toBe("default"); }) test("測試jest.fn()內部實現", () => { let mockFn = jest.fn((num1, num2) => { return num1 * num2; }) // 斷言mockFn執行后返回100 expect(mockFn(10, 10)).toBe(100); }) test("測試jest.fn()返回Promise", async () => { let mockFn = jest.fn().mockResolvedValue("default"); let result = await mockFn(); // 斷言mockFn通過await關鍵字執行后返回值為default expect(result).toBe("default"); // 斷言mockFn調用后返回的是Promise對象 expect(Object.prototype.toString.call(mockFn())).toBe("[object Promise]"); })
上面的代碼是jest.fn()提供的幾個常用的API和斷言語句,下面我們在src/fetch.js文件中寫一些被測試代碼,以更加接近業務的方式來理解Mock函數的實際應用。
被測試代碼中依賴了axios這個常用的請求庫和JSONPlaceholder這個上篇文章中提到免費的請求接口,請先在shell中執行npm install axios --save安裝依賴,。
// fetch.js import axios from "axios"; export default { async fetchPostsList(callback) { return axios.get("https://jsonplaceholder.typicode.com/posts").then(res => { return callback(res.data); }) } }
我們在fetch.js中封裝了一個fetchPostsList方法,該方法請求了JSONPlaceholder提供的接口,并通過傳入的回調函數返回處理過的返回值。如果我們想測試該接口能夠被正常請求,只需要捕獲到傳入的回調函數能夠被正常的調用即可。下面是functions.test.js中的測試的代碼。
import fetch from "../src/fetch.js" test("fetchPostsList中的回調函數應該能夠被調用", async () => { expect.assertions(1); let mockFn = jest.fn(); await fetch.fetchPostsList(mockFn); // 斷言mockFn被調用 expect(mockFn).toBeCalled(); })2. jest.mock()
fetch.js文件夾中封裝的請求方法可能我們在其他模塊被調用的時候,并不需要進行實際的請求(請求方法已經通過單側或需要該方法返回非真實數據)。此時,使用jest.mock()去mock整個模塊是十分有必要的。
下面我們在src/fetch.js的同級目錄下創建一個src/events.js。
// events.js import fetch from "./fetch"; export default { async getPostList() { return fetch.fetchPostsList(data => { console.log("fetchPostsList be called!"); // do something }); } }
functions.test.js中的測試代碼如下:
// functions.test.js import events from "../src/events"; import fetch from "../src/fetch"; jest.mock("../src/fetch.js"); test("mock 整個 fetch.js模塊", async () => { expect.assertions(2); await events.getPostList(); expect(fetch.fetchPostsList).toHaveBeenCalled(); expect(fetch.fetchPostsList).toHaveBeenCalledTimes(1); });
在測試代碼中我們使用了jest.mock("../src/fetch.js")去mock整個fetch.js模塊。如果注釋掉這行代碼,執行測試腳本時會出現以下報錯信息
從這個報錯中,我們可以總結出一個重要的結論:
在jest中如果想捕獲函數的調用情況,則該函數必須被mock或者spy!3. jest.spyOn()
jest.spyOn()方法同樣創建一個mock函數,但是該mock函數不僅能夠捕獲函數的調用情況,還可以正常的執行被spy的函數。實際上,jest.spyOn()是jest.fn()的語法糖,它創建了一個和被spy的函數具有相同內部代碼的mock函數。
上圖是之前jest.mock()的示例代碼中的正確執行結果的截圖,從shell腳本中可以看到console.log("fetchPostsList be called!");這行代碼并沒有在shell中被打印,這是因為通過jest.mock()后,模塊內的方法是不會被jest所實際執行的。這時我們就需要使用jest.spyOn()。
// functions.test.js import events from "../src/events"; import fetch from "../src/fetch"; test("使用jest.spyOn()監控fetch.fetchPostsList被正常調用", async() => { expect.assertions(2); const spyFn = jest.spyOn(fetch, "fetchPostsList"); await events.getPostList(); expect(spyFn).toHaveBeenCalled(); expect(spyFn).toHaveBeenCalledTimes(1); })
執行npm run test后,可以看到shell中的打印信息,說明通過jest.spyOn(),fetchPostsList被正常的執行了。
4. 總結這篇文章中我們介紹了jest.fn(),jest.mock()和jest.spyOn()來創建mock函數,通過mock函數我們可以通過以下三個特性去更好的編寫我們的測試代碼:
捕獲函數調用情況
設置函數返回值
改變函數的內部實現
在實際項目的單元測試中,jest.fn()常被用來進行某些有回調函數的測試;jest.mock()可以mock整個模塊中的方法,當某個模塊已經被單元測試100%覆蓋時,使用jest.mock()去mock該模塊,節約測試時間和測試的冗余度是十分必要;當需要測試某些必須被完整執行的方法時,常常需要使用jest.spyOn()。這些都需要開發者根據實際的業務代碼靈活選擇。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/98452.html
摘要:的測試不管在用還是都是很頭疼的事情但是自從有了一口氣寫個測試腰也不疼了頭也不疼了只需要個理由在說用測為什么好之前我們先來看我們要測的一個例子栗子比如我要寫一個模塊要去取用戶的和他所有的數量那么我們應該有一個的我們還需要一個的大同小異略去最后 from oyanglul.us Javascript 的測試, 不管在用 jasmine 還是 mocha, 都是很頭疼的事情. 但是自從有了...
摘要:現在,我們可以使用單元測試來提高自己的代碼質量。它在單元測試的編寫中通常用來模擬等相關請求。通過這篇文章,你應該學會了如何針對已有代碼從零開始編寫一套完整的單元測試用例。 概述 在日常的功能開發中,我們的代碼測試都依賴于自己或者QA進行測試。這些操作不僅費時費力,而且還依賴開發者自身的驅動。在開發一些第三方依賴的庫時,我們也沒有辦法給第三方提供完整的代碼質量報告。 現在,我們可以使用單...
摘要:單元測試針對程序模塊進行測試。是開源的單元測試工具。一個好的單元測試應該具備的條件安全重構已有代碼單元測試一個很重要的價值是為重構保駕護航。斷言外部依賴單元測試的一個重要原則就是無依賴和隔離。 前端測試金字塔 對于一個 Web 應用來說,理想的測試組合應該包含大量單元測試(unit tests),部分快照測試(snapshot tests),以及少量端到端測試(e2e tests)。參...
摘要:簡介是發布的一個開源的基于框架的單元測試工具。具體版本對照如下版本版本此處使用的版本為,所以我們需要安裝依賴安裝完成,接下來需要進行相關的配置。這樣就可以將測試集中在組件的結構和邏輯上。 Jest、Enzyme 簡介 Jest 是 Facebook 發布的一個開源的、基于 Jasmine 框架的 JavaScript 單元測試工具。 Enzyme 是 React 的測試類庫。 Enzy...
摘要:包包含由團隊提供的測試實用程序。將在一個名為的目錄中自動查找整個樹中的測試文件是的帶有下劃線。讓我們為時間軸組件創建第一個測試。其中之一是命令。現在我們已經編寫了第一個測試并確認了我們的設置我們將在明天開始測試我們的時間軸組件。 本文轉載自:眾成翻譯譯者:iOSDevLog鏈接:http://www.zcfy.cc/article/3807原文:https://www.fullstac...
閱讀 2879·2021-11-24 09:39
閱讀 3130·2021-11-19 10:00
閱讀 1535·2021-10-27 14:17
閱讀 1811·2021-10-14 09:43
閱讀 961·2021-09-03 10:30
閱讀 3413·2019-08-30 15:54
閱讀 2728·2019-08-30 13:05
閱讀 2006·2019-08-30 11:02