国产av日韩一区二区三区精品,成人性爱视频在线观看,国产,欧美,日韩,一区,www.成色av久久成人,2222eeee成人天堂

首頁 web前端 js教程 Jest 簡介:單元測試、模擬和非同步程式碼

Jest 簡介:單元測試、模擬和非同步程式碼

Nov 01, 2024 am 12:23 AM

Introduction to Jest: Unit Testing, Mocking, and Asynchronous Code

笑話簡介

Jest 是一個用來測試 JavaScript 程式碼的函式庫。

這是一個由 Facebook 維護的開源項目,它特別適合 React 程式碼測試,但不僅限於此:它可以測試任何 JavaScript 程式碼。它的優(yōu)點是:

  • 速度很快
  • 它可以執(zhí)行快照檢定
  • 它固執(zhí)己見,提供開箱即用的一切,無需您做出選擇
export default function sum(a, n) {
  return a + b;
}

divide.test.js

import sum from './sum';

// Describe the test and wrap it in a function.
it('adds 1 + 2 to equal 3', () => {
  const result = sum(1, 2);

  // Jest uses matchers, like pretty much any other JavaScript testing framework.
  // They're designed to be easy to get at a glance;
  // here, you're expecting `result` to be 3.
  expect(result).toBe(3);
});

匹配器

匹配器是一種可以讓您測試值的方法。

  • toBe 比較嚴格相等,使用 ===
  • toEqual 比較兩個變數(shù)的值。如果它是一個物件或數(shù)組,它會檢查所有屬性或元素的相等性
  • 傳遞 null 值時 toBeNull 為 true
  • 傳遞定義值時 toBeDefined 為 true(與上方相反)
  • 傳遞未定義值時 toBeUndefine 為 true
  • toBeCloseTo 用於比較浮點數(shù)值,避免捨入錯誤
  • toBeTruthy true 如果該值被視為 true (就像 if 那樣)
  • toBeFalsy 如果該值被認為是假(就像 if 一樣),則為 true
  • 如果 Expect() 的結(jié)果高於參數(shù)
  • ,則 toBeGreaterThan true
  • toBeGreaterThanOrEqual 如果 Expect() 的結(jié)果等於參數(shù)或高於參數(shù)
  • ,則為 true
  • 如果 Expect() 的結(jié)果低於參數(shù)
  • ,則 toBeLessThan true
  • toBeLessThanOrEqual 如果 Expect() 的結(jié)果等於參數(shù)或低於參數(shù)
  • ,則為 true
  • toMatch 用於將字串與正規(guī)表示式模式配對進行比較
  • toContain 用於數(shù)組,如果預(yù)期數(shù)組在其元素集中包含參數(shù)
  • ,則為 true
  • toHaveLength(number):檢查陣列的長度
  • toHaveProperty(key, value):檢查物件是否具有屬性,並可選擇檢查其值
  • toThrow 檢查您傳遞的函數(shù)是否拋出異常(一般情況下)或特定異常
  • toBeInstanceOf():檢查物件是否為類別的實例

依賴關(guān)係

依賴項是您的應(yīng)用程式所依賴的一段程式碼。它可以是我們專案中的函數(shù)/物件或第三方依賴項(例如 axios)

當您自己的應(yīng)用程式?jīng)]有一段程式碼就無法運作時,它就變成真正的依賴項。

例如,如果您在應(yīng)用程式中實作一項功能來傳送電子郵件或發(fā)出 api 請求或建置設(shè)定物件等

兩種方法我們可以在js專案的程式碼中加入依賴項:

進口

export default function sum(a, n) {
  return a + b;
}

依賴注入

只是一個簡單概念的奇特術(shù)語。

如果您的函數(shù)需要外部相依性的某些功能,只需將其作為參數(shù)注入即可。

import sum from './sum';

// Describe the test and wrap it in a function.
it('adds 1 + 2 to equal 3', () => {
  const result = sum(1, 2);

  // Jest uses matchers, like pretty much any other JavaScript testing framework.
  // They're designed to be easy to get at a glance;
  // here, you're expecting `result` to be 3.
  expect(result).toBe(3);
});

單元測試

單元測試由軟體開發(fā)人員編寫和運行,以確保應(yīng)用程式的一部分(稱為「單元」)滿足其設(shè)計並按預(yù)期運行。

我們想要單獨測試我們的程式碼,我們不關(guān)心任何依賴項的實際實作。
我們想要驗證

  • 我們的程式碼單元如預(yù)期般運作
  • 回傳預(yù)期結(jié)果
  • 以其應(yīng)有的方式呼叫任何協(xié)作者(依賴項)

這就是模擬我們的依賴關(guān)係發(fā)揮作用的地方。

嘲笑

在單元測試中,模擬為我們提供了存根依賴項所提供的功能的能力,以及意味著觀察我們的程式碼如何與依賴項互動。

當將依賴項直接包含到我們的測試中成本昂貴或不切實際時,例如,當您的程式碼對 API 進行 HTTP 呼叫或與資料庫層互動時,模擬特別有用。

最好刪除這些依賴項的回應(yīng),同時確保它們按要求被呼叫。這就是模擬派上用場的地方。

透過使用模擬函數(shù),我們可以知道以下:

  • 收到的來電數(shù)量。
  • 參數(shù) 每次呼叫時使用的值。
  • 每次呼叫時的「上下文」或這個值。
  • 函數(shù)如何退出以及產(chǎn)生了哪些值。

開玩笑地嘲笑

建立模擬函數(shù)有多種方法。

  • jest.fn 方法讓我們可以直接建立一個新的模擬函數(shù)。
  • 如果您正在模擬物件方法,則可以使用 jest.spyOn。
  • 如果你想模擬整個模組,你可以使用 jest.mock。

jest.fn 方法本身就是一個高階函數(shù)。

這是一個工廠方法,用於建立新的、未使用的模擬函數(shù)。

JavaScript 中的函數(shù)是一等公民,它們可以作為參數(shù)傳遞。

每個模擬函數(shù)都有一些特殊的性質(zhì)。模擬屬性是基礎(chǔ)。此屬性是一個對象,其中包含有關(guān)如何呼叫函數(shù)的所有模擬狀態(tài)資訊。該物件包含三個數(shù)組屬性:

  • 呼叫 [每次呼叫的參數(shù)]
  • 實例 [每次呼叫時的「this」值]
  • Results [函數(shù)退出的值],results 屬性有型別(return 或 throw)和值
    • 函數(shù)明確傳回一個值。
    • 函數(shù)運行完成,沒有 return 語句(相當於回傳 undefined
    • 函數(shù)拋出錯誤。
export default function sum(a, n) {
  return a + b;
}
  • https://codesandbox.io/s/implementing-mock-functions-tkc8b

模擬基礎(chǔ)

import sum from './sum';

// Describe the test and wrap it in a function.
it('adds 1 + 2 to equal 3', () => {
  const result = sum(1, 2);

  // Jest uses matchers, like pretty much any other JavaScript testing framework.
  // They're designed to be easy to get at a glance;
  // here, you're expecting `result` to be 3.
  expect(result).toBe(3);
});

模擬注入的依賴項

import { name, draw, reportArea, reportPerimeter } from './modules/square.js';

類比模組

使用 jest.fn 模擬函數(shù)

// Constructor Injection

// DatabaseManager class takes a database connector as a dependency
class DatabaseManager {
    constructor(databaseConnector) {
        // Dependency injection of the database connector
        this.databaseConnector = databaseConnector;
    }

    updateRow(rowId, data) {
        // Use the injected database connector to perform the update
        this.databaseConnector.update(rowId, data);
    }
}

// parameter injection, takes a database connector instance in as an argument; easy to test!
function updateRow(rowId, data, databaseConnector) {
    databaseConnector.update(rowId, data);
}

這種類型的嘲笑不太常見,原因如下:

  • jest.mock 會自動為模組中的所有函數(shù)執(zhí)行此操作
  • jest.spyOn 做同樣的事情,但允許恢復(fù)原始功能

使用 jest.mock 類比模組

更常見的方法是使用 jest.mock 自動將模組的所有匯出設(shè)定為 Mock 函數(shù)

// 1. The mock function factory
function fn(impl = () => {}) {
  // 2. The mock function
  const mockFn = function(...args) {
    // 4. Store the arguments used
    mockFn.mock.calls.push(args);
    mockFn.mock.instances.push(this);
    try {
      const value = impl.apply(this, args); // call impl, passing the right this
      mockFn.mock.results.push({ type: 'return', value });
      return value; // return the value
    } catch (value) {
      mockFn.mock.results.push({ type: 'throw', value });
      throw value; // re-throw the error
    }
  }
  // 3. Mock state
  mockFn.mock = { calls: [], instances: [], results: [] };
  return mockFn;
}

使用 jest.spyOn 監(jiān)視或模擬函數(shù)

有時您只想觀看一個方法被調(diào)用,但保留原始實作。其他時候,您可能想要模擬實現(xiàn),但稍後在套件中恢復(fù)原始版本。

test("returns undefined by default", () => {
  const mock = jest.fn();

  let result = mock("foo");

  expect(result).toBeUndefined();
  expect(mock).toHaveBeenCalled();
  expect(mock).toHaveBeenCalledTimes(1);
  expect(mock).toHaveBeenCalledWith("foo");
});

恢復(fù)原來的實現(xiàn)

const doAdd = (a, b, callback) => {
  callback(a + b);
};

test("calls callback with arguments added", () => {
  const mockCallback = jest.fn();
  doAdd(1, 2, mockCallback);
  expect(mockCallback).toHaveBeenCalledWith(3);
});

JavaScript 和事件循環(huán)

JavaScript 是單執(zhí)行緒的: 一次只能執(zhí)行一個任務(wù)。通常這沒什麼大不了的,但現(xiàn)在想像一下你正在運行一個需要30 秒的任務(wù).. 是的.. 在該任務(wù)期間,我們等待30 秒,然後才會發(fā)生其他事情(JavaScript 默認在瀏覽器的主線程上運行,所以整個UI都卡住了)。
現(xiàn)在是 2020 年,沒有人想要一個緩慢、反應(yīng)遲鈍的網(wǎng)站。

幸運的是,瀏覽器為我們提供了一些 JavaScript 引擎本身不提供的功能:Web API。這包括 DOM APIsetTimeout、HTTP 請求 等。這可以幫助我們創(chuàng)建一些非同步,非阻塞行為

export default function sum(a, n) {
  return a + b;
}
  • 呼叫堆疊 - 當我們呼叫一個函數(shù)時,它會被加入到稱為呼叫堆疊的東西。
  • WebAPI - setTimeout 由 WebAPI 提供,採用回調(diào)函數(shù)並設(shè)定計時器,而不阻塞主執(zhí)行緒
  • 佇列 - 當計時器結(jié)束時,回呼被加入到佇列
  • 事件循環(huán) - 檢查呼叫堆疊是否為空,檢查佇列中是否有要執(zhí)行的回調(diào),然後移至要執(zhí)行的呼叫堆疊
import sum from './sum';

// Describe the test and wrap it in a function.
it('adds 1 + 2 to equal 3', () => {
  const result = sum(1, 2);

  // Jest uses matchers, like pretty much any other JavaScript testing framework.
  // They're designed to be easy to get at a glance;
  // here, you're expecting `result` to be 3.
  expect(result).toBe(3);
});

使用 Jest 測試非同步程式碼

Jest 通常希望同步執(zhí)行測試的函數(shù)

如果我們執(zhí)行非同步操作,但我們不讓 Jest 知道它應(yīng)該等待測試結(jié)束,則會給出誤報。

import { name, draw, reportArea, reportPerimeter } from './modules/square.js';

非同步模式
JavaScript 中有多種處理非同步操作的模式;最常用的是:

  • 回調(diào)
  • Promise 和非同步/等待

測試回調(diào)

你不能在回調(diào)中進行測試,因為 Jest 不會執(zhí)行它 - 測試檔案的執(zhí)行在回呼被呼叫之前結(jié)束。要解決此問題,請將參數(shù)傳遞給測試函數(shù),您可以方便地呼叫“done”。 Jest 會等到您呼叫 done() 後再結(jié)束測試:

// Constructor Injection

// DatabaseManager class takes a database connector as a dependency
class DatabaseManager {
    constructor(databaseConnector) {
        // Dependency injection of the database connector
        this.databaseConnector = databaseConnector;
    }

    updateRow(rowId, data) {
        // Use the injected database connector to perform the update
        this.databaseConnector.update(rowId, data);
    }
}

// parameter injection, takes a database connector instance in as an argument; easy to test!
function updateRow(rowId, data, databaseConnector) {
    databaseConnector.update(rowId, data);
}

承諾

對於傳回 Promise 的函數(shù),我們從測試中傳回一個 Promise:

// 1. The mock function factory
function fn(impl = () => {}) {
  // 2. The mock function
  const mockFn = function(...args) {
    // 4. Store the arguments used
    mockFn.mock.calls.push(args);
    mockFn.mock.instances.push(this);
    try {
      const value = impl.apply(this, args); // call impl, passing the right this
      mockFn.mock.results.push({ type: 'return', value });
      return value; // return the value
    } catch (value) {
      mockFn.mock.results.push({ type: 'throw', value });
      throw value; // re-throw the error
    }
  }
  // 3. Mock state
  mockFn.mock = { calls: [], instances: [], results: [] };
  return mockFn;
}

異步/等待

為了測試傳回 Promise 的函數(shù),我們也可以使用 async/await,這使得語法非常簡單明了:

test("returns undefined by default", () => {
  const mock = jest.fn();

  let result = mock("foo");

  expect(result).toBeUndefined();
  expect(mock).toHaveBeenCalled();
  expect(mock).toHaveBeenCalledTimes(1);
  expect(mock).toHaveBeenCalledWith("foo");
});

尖端

  • 我們需要很好地理解我們的函數(shù)的作用以及我們要測試的內(nèi)容
  • 思考我們正在測試的程式碼的行為
  • 設(shè)定舞臺:
    • 模擬/監(jiān)視任何依賴項
    • 我們的程式碼是否與全域物件互動?我們也可以嘲笑/監(jiān)視他們
    • 我們的測驗是否與 DOM 互動?我們可以建構(gòu)一些假元素來使用
    • 建構(gòu)你的測驗
    • 鑑於...
    • 我打電話時......
    • 然後...我期待......
const doAdd = (a, b, callback) => {
  callback(a + b);
};

test("calls callback with arguments added", () => {
  const mockCallback = jest.fn();
  doAdd(1, 2, mockCallback);
  expect(mockCallback).toHaveBeenCalledWith(3);
});

連結(jié)

  • https://medium.com/@rickhanlonii/understanding-jest-mocks-f0046c68e53c
  • https://jestjs.io/docs/en/mock-functions
  • https://codesandbox.io/s/implementing-mock-functions-tkc8b
  • https://github.com/BulbEnergy/jest-mock-examples
  • https://dev.to/lydiahallie/javascript-visualized-event-loop-3dif
  • https://jestjs.io/docs/en/asynchronous
  • https://www.pluralsight.com/guides/test-asynchronous-code-jest

以上是Jest 簡介:單元測試、模擬和非同步程式碼的詳細內(nèi)容。更多資訊請關(guān)注PHP中文網(wǎng)其他相關(guān)文章!

本網(wǎng)站聲明
本文內(nèi)容由網(wǎng)友自願投稿,版權(quán)歸原作者所有。本站不承擔相應(yīng)的法律責任。如發(fā)現(xiàn)涉嫌抄襲或侵權(quán)的內(nèi)容,請聯(lián)絡(luò)admin@php.cn

熱AI工具

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅(qū)動的應(yīng)用程序,用於創(chuàng)建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

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

Clothoff.io

Clothoff.io

AI脫衣器

Video Face Swap

Video Face Swap

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

熱工具

記事本++7.3.1

記事本++7.3.1

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

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發(fā)環(huán)境

Dreamweaver CS6

Dreamweaver CS6

視覺化網(wǎng)頁開發(fā)工具

SublimeText3 Mac版

SublimeText3 Mac版

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

Java vs. JavaScript:清除混亂 Java vs. JavaScript:清除混亂 Jun 20, 2025 am 12:27 AM

Java和JavaScript是不同的編程語言,各自適用於不同的應(yīng)用場景。 Java用於大型企業(yè)和移動應(yīng)用開發(fā),而JavaScript主要用於網(wǎng)頁開發(fā)。

JavaScript評論:簡短說明 JavaScript評論:簡短說明 Jun 19, 2025 am 12:40 AM

JavascriptconcommentsenceenceEncorenceEnterential gransimenting,reading and guidingCodeeXecution.1)單inecommentsareusedforquickexplanations.2)多l(xiāng)inecommentsexplaincomplexlogicorprovideDocumentation.3)

為什麼要將標籤放在的底部? 為什麼要將標籤放在的底部? Jul 02, 2025 am 01:22 AM

PlacingtagsatthebottomofablogpostorwebpageservespracticalpurposesforSEO,userexperience,anddesign.1.IthelpswithSEObyallowingsearchenginestoaccesskeyword-relevanttagswithoutclutteringthemaincontent.2.Itimprovesuserexperiencebykeepingthefocusonthearticl

如何在JS中與日期和時間合作? 如何在JS中與日期和時間合作? Jul 01, 2025 am 01:27 AM

JavaScript中的日期和時間處理需注意以下幾點:1.創(chuàng)建Date對像有多種方式,推薦使用ISO格式字符串以保證兼容性;2.獲取和設(shè)置時間信息可用get和set方法,注意月份從0開始;3.手動格式化日期需拼接字符串,也可使用第三方庫;4.處理時區(qū)問題建議使用支持時區(qū)的庫,如Luxon。掌握這些要點能有效避免常見錯誤。

JavaScript與Java:開發(fā)人員的全面比較 JavaScript與Java:開發(fā)人員的全面比較 Jun 20, 2025 am 12:21 AM

JavaScriptIspreferredforredforwebdevelverment,而Javaisbetterforlarge-ScalebackendsystystemsandSandAndRoidApps.1)JavascriptexcelcelsincreatingInteractiveWebexperienceswebexperienceswithitswithitsdynamicnnamicnnamicnnamicnnamicnemicnemicnemicnemicnemicnemicnemicnemicnddommanipulation.2)

什麼是在DOM中冒泡和捕獲的事件? 什麼是在DOM中冒泡和捕獲的事件? Jul 02, 2025 am 01:19 AM

事件捕獲和冒泡是DOM中事件傳播的兩個階段,捕獲是從頂層向下到目標元素,冒泡是從目標元素向上傳播到頂層。 1.事件捕獲通過addEventListener的useCapture參數(shù)設(shè)為true實現(xiàn);2.事件冒泡是默認行為,useCapture設(shè)為false或省略;3.可使用event.stopPropagation()阻止事件傳播;4.冒泡支持事件委託,提高動態(tài)內(nèi)容處理效率;5.捕獲可用於提前攔截事件,如日誌記錄或錯誤處理。了解這兩個階段有助於精確控制JavaScript響應(yīng)用戶操作的時機和方式。

JavaScript:探索用於高效編碼的數(shù)據(jù)類型 JavaScript:探索用於高效編碼的數(shù)據(jù)類型 Jun 20, 2025 am 12:46 AM

javascripthassevenfundaMentalDatatypes:數(shù)字,弦,布爾值,未定義,null,object和symbol.1)numberSeadUble-eaduble-ecisionFormat,forwidevaluerangesbutbecautious.2)

如何減少JavaScript應(yīng)用程序的有效載荷大??? 如何減少JavaScript應(yīng)用程序的有效載荷大??? Jun 26, 2025 am 12:54 AM

如果JavaScript應(yīng)用加載慢、性能差,問題往往出在payload太大,解決方法包括:1.使用代碼拆分(CodeSplitting),通過React.lazy()或構(gòu)建工具將大bundle拆分為多個小文件,按需加載以減少首次下載量;2.移除未使用的代碼(TreeShaking),利用ES6模塊機制清除“死代碼”,確保引入的庫支持該特性;3.壓縮和合併資源文件,啟用Gzip/Brotli和Terser壓縮JS,合理合併文件並優(yōu)化靜態(tài)資源;4.替換重型依賴,選用輕量級庫如day.js、fetch

See all articles