成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

使用Jest測(cè)試JavaScript(Mock篇)

YorkChen / 1101人閱讀

摘要:測(cè)試調(diào)用斷言的執(zhí)行后返回?cái)嘌员徽{(diào)用斷言被調(diào)用了一次斷言傳入的參數(shù)為所創(chuàng)建的函數(shù)還可以設(shè)置返回值,定義內(nèi)部實(shí)現(xiàn)或返回對(duì)象。

在本篇教程中,我們會(huì)介紹 Jest 中的三個(gè)與 Mock 函數(shù)相關(guān)的API,分別是jest.fn()、jest.spyOn()jest.mock()。使用它們創(chuàng)建Mock函數(shù)能夠幫助我們更好的測(cè)試項(xiàng)目中一些邏輯較復(fù)雜的代碼,例如測(cè)試函數(shù)的嵌套調(diào)用,回調(diào)函數(shù)的調(diào)用等。

如果你還不知道Jest的基本使用方法,請(qǐng)先閱讀: 《使用Jest測(cè)試JavaScript (入門(mén)篇)》
為什么要使用Mock函數(shù)?

在項(xiàng)目中,一個(gè)模塊的方法內(nèi)常常會(huì)去調(diào)用另外一個(gè)模塊的方法。在單元測(cè)試中,我們可能并不需要關(guān)心內(nèi)部調(diào)用的方法的執(zhí)行過(guò)程和結(jié)果,只想知道它是否被正確調(diào)用即可,甚至?xí)付ㄔ摵瘮?shù)的返回值。此時(shí),使用Mock函數(shù)是十分有必要。

Mock函數(shù)提供的以下三種特性,在我們寫(xiě)測(cè)試代碼時(shí)十分有用:

捕獲函數(shù)調(diào)用情況

設(shè)置函數(shù)返回值

改變函數(shù)的內(nèi)部實(shí)現(xiàn)

我們接著使用上篇文章中的目錄結(jié)構(gòu),在test/functions.test.js文件中編寫(xiě)測(cè)試代碼,src/目錄下寫(xiě)被測(cè)試代碼。
1. jest.fn()

jest.fn()是創(chuàng)建Mock函數(shù)最簡(jiǎn)單的方式,如果沒(méi)有定義函數(shù)內(nèi)部的實(shí)現(xiàn),jest.fn()會(huì)返回undefined作為返回值。

// functions.test.js

test("測(cè)試jest.fn()調(diào)用", () => {
  let mockFn = jest.fn();
  let result = mockFn(1, 2, 3);

  // 斷言mockFn的執(zhí)行后返回undefined
  expect(result).toBeUndefined();
  // 斷言mockFn被調(diào)用
  expect(mockFn).toBeCalled();
  // 斷言mockFn被調(diào)用了一次
  expect(mockFn).toBeCalledTimes(1);
  // 斷言mockFn傳入的參數(shù)為1, 2, 3
  expect(mockFn).toHaveBeenCalledWith(1, 2, 3);
})

jest.fn()所創(chuàng)建的Mock函數(shù)還可以設(shè)置返回值,定義內(nèi)部實(shí)現(xiàn)返回Promise對(duì)象。

// functions.test.js

test("測(cè)試jest.fn()返回固定值", () => {
  let mockFn = jest.fn().mockReturnValue("default");
  // 斷言mockFn執(zhí)行后返回值為default
  expect(mockFn()).toBe("default");
})

test("測(cè)試jest.fn()內(nèi)部實(shí)現(xiàn)", () => {
  let mockFn = jest.fn((num1, num2) => {
    return num1 * num2;
  })
  // 斷言mockFn執(zhí)行后返回100
  expect(mockFn(10, 10)).toBe(100);
})

test("測(cè)試jest.fn()返回Promise", async () => {
  let mockFn = jest.fn().mockResolvedValue("default");
  let result = await mockFn();
  // 斷言mockFn通過(guò)await關(guān)鍵字執(zhí)行后返回值為default
  expect(result).toBe("default");
  // 斷言mockFn調(diào)用后返回的是Promise對(duì)象
  expect(Object.prototype.toString.call(mockFn())).toBe("[object Promise]");
})

上面的代碼是jest.fn()提供的幾個(gè)常用的API和斷言語(yǔ)句,下面我們?cè)?b>src/fetch.js文件中寫(xiě)一些被測(cè)試代碼,以更加接近業(yè)務(wù)的方式來(lái)理解Mock函數(shù)的實(shí)際應(yīng)用。

被測(cè)試代碼中依賴了axios這個(gè)常用的請(qǐng)求庫(kù)和JSONPlaceholder這個(gè)上篇文章中提到免費(fèi)的請(qǐng)求接口,請(qǐng)先在shell中執(zhí)行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);
    })
  }
}

我們?cè)?b>fetch.js中封裝了一個(gè)fetchPostsList方法,該方法請(qǐng)求了JSONPlaceholder提供的接口,并通過(guò)傳入的回調(diào)函數(shù)返回處理過(guò)的返回值。如果我們想測(cè)試該接口能夠被正常請(qǐng)求,只需要捕獲到傳入的回調(diào)函數(shù)能夠被正常的調(diào)用即可。下面是functions.test.js中的測(cè)試的代碼。

import fetch from "../src/fetch.js"

test("fetchPostsList中的回調(diào)函數(shù)應(yīng)該能夠被調(diào)用", async () => {
  expect.assertions(1);
  let mockFn = jest.fn();
  await fetch.fetchPostsList(mockFn);

  // 斷言mockFn被調(diào)用
  expect(mockFn).toBeCalled();
})
2. jest.mock()

fetch.js文件夾中封裝的請(qǐng)求方法可能我們?cè)谄渌K被調(diào)用的時(shí)候,并不需要進(jìn)行實(shí)際的請(qǐng)求(請(qǐng)求方法已經(jīng)通過(guò)單側(cè)或需要該方法返回非真實(shí)數(shù)據(jù))。此時(shí),使用jest.mock()去mock整個(gè)模塊是十分有必要的。

下面我們?cè)?b>src/fetch.js的同級(jí)目錄下創(chuàng)建一個(gè)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中的測(cè)試代碼如下:

// functions.test.js

import events from "../src/events";
import fetch from "../src/fetch";

jest.mock("../src/fetch.js");

test("mock 整個(gè) fetch.js模塊", async () => {
  expect.assertions(2);
  await events.getPostList();
  expect(fetch.fetchPostsList).toHaveBeenCalled();
  expect(fetch.fetchPostsList).toHaveBeenCalledTimes(1);
});

在測(cè)試代碼中我們使用了jest.mock("../src/fetch.js")去mock整個(gè)fetch.js模塊。如果注釋掉這行代碼,執(zhí)行測(cè)試腳本時(shí)會(huì)出現(xiàn)以下報(bào)錯(cuò)信息

從這個(gè)報(bào)錯(cuò)中,我們可以總結(jié)出一個(gè)重要的結(jié)論:

在jest中如果想捕獲函數(shù)的調(diào)用情況,則該函數(shù)必須被mock或者spy!
3. jest.spyOn()

jest.spyOn()方法同樣創(chuàng)建一個(gè)mock函數(shù),但是該mock函數(shù)不僅能夠捕獲函數(shù)的調(diào)用情況,還可以正常的執(zhí)行被spy的函數(shù)。實(shí)際上,jest.spyOn()jest.fn()的語(yǔ)法糖,它創(chuàng)建了一個(gè)和被spy的函數(shù)具有相同內(nèi)部代碼的mock函數(shù)。

上圖是之前jest.mock()的示例代碼中的正確執(zhí)行結(jié)果的截圖,從shell腳本中可以看到console.log("fetchPostsList be called!");這行代碼并沒(méi)有在shell中被打印,這是因?yàn)橥ㄟ^(guò)jest.mock()后,模塊內(nèi)的方法是不會(huì)被jest所實(shí)際執(zhí)行的。這時(shí)我們就需要使用jest.spyOn()。

// functions.test.js

import events from "../src/events";
import fetch from "../src/fetch";

test("使用jest.spyOn()監(jiān)控fetch.fetchPostsList被正常調(diào)用", async() => {
  expect.assertions(2);
  const spyFn = jest.spyOn(fetch, "fetchPostsList");
  await events.getPostList();
  expect(spyFn).toHaveBeenCalled();
  expect(spyFn).toHaveBeenCalledTimes(1);
})

執(zhí)行npm run test后,可以看到shell中的打印信息,說(shuō)明通過(guò)jest.spyOn()fetchPostsList被正常的執(zhí)行了。

4. 總結(jié)

這篇文章中我們介紹了jest.fn(),jest.mock()jest.spyOn()來(lái)創(chuàng)建mock函數(shù),通過(guò)mock函數(shù)我們可以通過(guò)以下三個(gè)特性去更好的編寫(xiě)我們的測(cè)試代碼:

捕獲函數(shù)調(diào)用情況

設(shè)置函數(shù)返回值

改變函數(shù)的內(nèi)部實(shí)現(xiàn)

在實(shí)際項(xiàng)目的單元測(cè)試中,jest.fn()常被用來(lái)進(jìn)行某些有回調(diào)函數(shù)的測(cè)試;jest.mock()可以mock整個(gè)模塊中的方法,當(dāng)某個(gè)模塊已經(jīng)被單元測(cè)試100%覆蓋時(shí),使用jest.mock()去mock該模塊,節(jié)約測(cè)試時(shí)間和測(cè)試的冗余度是十分必要;當(dāng)需要測(cè)試某些必須被完整執(zhí)行的方法時(shí),常常需要使用jest.spyOn()。這些都需要開(kāi)發(fā)者根據(jù)實(shí)際的業(yè)務(wù)代碼靈活選擇。

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/98452.html

相關(guān)文章

  • [gist]用 jest 輕松測(cè)試 JavaScript

    摘要:的測(cè)試不管在用還是都是很頭疼的事情但是自從有了一口氣寫(xiě)個(gè)測(cè)試腰也不疼了頭也不疼了只需要個(gè)理由在說(shuō)用測(cè)為什么好之前我們先來(lái)看我們要測(cè)的一個(gè)例子栗子比如我要寫(xiě)一個(gè)模塊要去取用戶的和他所有的數(shù)量那么我們應(yīng)該有一個(gè)的我們還需要一個(gè)的大同小異略去最后 from oyanglul.us Javascript 的測(cè)試, 不管在用 jasmine 還是 mocha, 都是很頭疼的事情. 但是自從有了...

    CoderStudy 評(píng)論0 收藏0
  • 提高代碼質(zhì)量——使用Jest和Sinon給已有的代碼添加單元測(cè)試

    摘要:現(xiàn)在,我們可以使用單元測(cè)試來(lái)提高自己的代碼質(zhì)量。它在單元測(cè)試的編寫(xiě)中通常用來(lái)模擬等相關(guān)請(qǐng)求。通過(guò)這篇文章,你應(yīng)該學(xué)會(huì)了如何針對(duì)已有代碼從零開(kāi)始編寫(xiě)一套完整的單元測(cè)試用例。 概述 在日常的功能開(kāi)發(fā)中,我們的代碼測(cè)試都依賴于自己或者QA進(jìn)行測(cè)試。這些操作不僅費(fèi)時(shí)費(fèi)力,而且還依賴開(kāi)發(fā)者自身的驅(qū)動(dòng)。在開(kāi)發(fā)一些第三方依賴的庫(kù)時(shí),我們也沒(méi)有辦法給第三方提供完整的代碼質(zhì)量報(bào)告。 現(xiàn)在,我們可以使用單...

    voyagelab 評(píng)論0 收藏0
  • React 測(cè)試指南

    摘要:?jiǎn)卧獪y(cè)試針對(duì)程序模塊進(jìn)行測(cè)試。是開(kāi)源的單元測(cè)試工具。一個(gè)好的單元測(cè)試應(yīng)該具備的條件安全重構(gòu)已有代碼單元測(cè)試一個(gè)很重要的價(jià)值是為重構(gòu)保駕護(hù)航。斷言外部依賴單元測(cè)試的一個(gè)重要原則就是無(wú)依賴和隔離。 前端測(cè)試金字塔 對(duì)于一個(gè) Web 應(yīng)用來(lái)說(shuō),理想的測(cè)試組合應(yīng)該包含大量單元測(cè)試(unit tests),部分快照測(cè)試(snapshot tests),以及少量端到端測(cè)試(e2e tests)。參...

    Tecode 評(píng)論0 收藏0
  • Jest + Enzyme 前端自動(dòng)化測(cè)試

    摘要:簡(jiǎn)介是發(fā)布的一個(gè)開(kāi)源的基于框架的單元測(cè)試工具。具體版本對(duì)照如下版本版本此處使用的版本為,所以我們需要安裝依賴安裝完成,接下來(lái)需要進(jìn)行相關(guān)的配置。這樣就可以將測(cè)試集中在組件的結(jié)構(gòu)和邏輯上。 Jest、Enzyme 簡(jiǎn)介 Jest 是 Facebook 發(fā)布的一個(gè)開(kāi)源的、基于 Jasmine 框架的 JavaScript 單元測(cè)試工具。 Enzyme 是 React 的測(cè)試類庫(kù)。 Enzy...

    xushaojieaaa 評(píng)論0 收藏0
  • 【全棧React】第23天: 實(shí)現(xiàn)測(cè)試

    摘要:包包含由團(tuán)隊(duì)提供的測(cè)試實(shí)用程序。將在一個(gè)名為的目錄中自動(dòng)查找整個(gè)樹(shù)中的測(cè)試文件是的帶有下劃線。讓我們?yōu)闀r(shí)間軸組件創(chuàng)建第一個(gè)測(cè)試。其中之一是命令?,F(xiàn)在我們已經(jīng)編寫(xiě)了第一個(gè)測(cè)試并確認(rèn)了我們的設(shè)置我們將在明天開(kāi)始測(cè)試我們的時(shí)間軸組件。 本文轉(zhuǎn)載自:眾成翻譯譯者:iOSDevLog鏈接:http://www.zcfy.cc/article/3807原文:https://www.fullstac...

    airborne007 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

閱讀需要支付1元查看
<