欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

詳解如何使用Jest測試React組件

 更新時間:2023年10月09日 11:09:41   作者:托兒所夜十三  
在本文中,我們將了解如何使用Jest(Facebook 維護的一個測試框架)來測試我們的React組件,我們將首先了解如何在純 JavaScript 函數(shù)上使用 Jest,然后再了解它提供的一些開箱即用的功能,這些功能專門用于使測試 React 應(yīng)用程序變得更容易,需要的朋友可以參考下

值得注意的是,Jest 并不是專門針對 React:您可以使用它來測試任何 JavaScript 應(yīng)用程序。然而,它提供的一些功能對于測試用戶界面來說非常方便,這就是為什么它非常適合 React。

應(yīng)用測試示例

在我們測試任何東西之前,我們需要一個應(yīng)用程序來測試!您可以在GitHub上找到它以及我們即將編寫的所有測試。如果您想使用該應(yīng)用程序來感受一下,您還可以在線找到現(xiàn)場演示。

該應(yīng)用程序使用 ES2015 編寫的,使用帶有 Babel ES2015 和 React 預(yù)設(shè)的 webpack 進行編譯。我不會詳細介紹構(gòu)建設(shè)置,但如果您想查看的話,一切都在GitHub存儲庫中。您可以在自述文件中找到有關(guān)如何在本地運行應(yīng)用程序的完整說明。

應(yīng)用程序的入口是app/index.js

render(
  <Todos />,
  document.getElementById('app')
);

Todos組件是應(yīng)用程序的主要內(nèi)容。它包含所有狀態(tài)(該應(yīng)用程序的硬編碼數(shù)據(jù),實際上可能來自 API 或類似數(shù)據(jù)),并有渲染兩個子組件。

因為Todos組件包含所有狀態(tài),所以每當(dāng)有任何變化時,它需要TodoAddTodo組件通知它。因此,它將函數(shù)向下傳遞到這些組件中,當(dāng)某些數(shù)據(jù)發(fā)生變化時它們可以調(diào)用這些函數(shù),并Todos可以相應(yīng)地更新狀態(tài)。

最后,現(xiàn)在您會注意到所有業(yè)務(wù)邏輯都包含在app/state-functions.js

export function toggleDone(todos, id) {…}
export function addTodo(todos, todo) {…}
export function deleteTodo(todos, id) {…}

如果您熟悉 Redux,它們與 Redux 所謂的reducer非常相似。事實上,如果這個應(yīng)用程序變得更大,會考慮遷移到 Redux 以獲得更明確、結(jié)構(gòu)化的數(shù)據(jù)方法。

選擇 TDD 而不是 TDD?

關(guān)于測試驅(qū)動開發(fā)的優(yōu)缺點已經(jīng)有很多文章寫過了,開發(fā)人員需要先編寫測試,然后再編寫修復(fù)測試的代碼。這背后的想法是,通過先編寫測試,您必須思考您正在編寫的API,并且它可能會導(dǎo)致更好的設(shè)計。我認為這在很大程度上取決于個人偏好和測試的類型。我發(fā)現(xiàn),對于React組件,我喜歡先編寫組件,然后為最重要的功能添加測試。然而,如果您發(fā)現(xiàn)先為組件編寫測試符合您的工作流程,那么您應(yīng)該這樣做。在這里沒有硬性規(guī)定,做適合您和您的團隊感覺最好的事情。

什么是Jest

Jest首次發(fā)布于2014年,盡管它最初引起了很多關(guān)注,但該項目一度停滯不前,并沒有得到很積極的開發(fā)。然而,F(xiàn)acebook投入了大量精力來改進Jest,并發(fā)布了一些令人印象深刻的變化,值得重新考慮。與最初的開源發(fā)布相比,Jest僅保留了名稱和標(biāo)志。其他一切都已經(jīng)改變和重寫。如果您想了解更多信息,可以閱讀Christoph Pojer的評論,他在其中討論了該項目的當(dāng)前狀態(tài)。

如果您對使用其他框架設(shè)置Babel、React和JSX測試感到沮喪,那么我強烈建議您嘗試Jest。如果您發(fā)現(xiàn)現(xiàn)有的測試安裝速度很慢,我也強烈推薦Jest。它可以自動并行運行測試,其watch模式能夠運行與更改文件相關(guān)的測試,這在您擁有大量測試套件時是非常寶貴的。它已經(jīng)配置了JSDom,這意味著您可以編寫瀏覽器測試但通過Node運行它們。它可以處理異步測試,并且具有內(nèi)置的高級功能,如mocking、spy和stub。

安裝和配置 Jest

首先,我們需要安裝 Jest。因為我們也在使用 Babel,所以我們將安裝另外幾個模塊,使 Jest 和 Babel 可以正常使用:

npm install --save-dev jest babel-jest @babel/core @babel/preset-env @babel/preset-react

您還需要一個babel.config.js包含 Babel 配置的文件,以使用您需要的任何預(yù)設(shè)和插件。如下所示:

module.exports = {
  presets: [
    '@babel/preset-env',
    '@babel/preset-react',
  ],
};

本文不會深入探討 Babel 的設(shè)置。如果您想具體了解有關(guān) Babel 的更多信息,我推薦Babel 使用指南。

我們還不會安裝任何 React 測試工具,因為我們不會從測試組件開始,而是從測試狀態(tài)函數(shù)開始。

Jest 期望在一個文件夾中找到我們的測試__tests__,這已成為 JavaScript 社區(qū)中的一種流行慣例,我們將在這里堅持這一慣例。如果您不喜歡該__tests__設(shè)置,開箱即用的 Jest 還支持查找任何.test.js文件.spec.js。

由于我們將測試我們的狀態(tài)函數(shù),因此請繼續(xù)創(chuàng)建__tests__/state-functions.test.js。 下面是一個測試用例,進行測試檢查Jest配置是否正常。

describe('Addition', () => {
  it('knows that 2 and 2 make 4', () => {
    expect(2 + 2).toBe(4);
  });
});

現(xiàn)在,進入您的package.json, 添加npm test命令:

"scripts": {
  "test": "jest"
}

如果您現(xiàn)在執(zhí)行npm test命令,您應(yīng)該會看到測試運行并通過!

PASS  __tests__/state-functions.test.js
  Addition
    ? knows that 2 and 2 make 4 (5ms)
Test Suites: 1 passed, 1 total
Tests:       1 passed, 1 total
Snapshots:   0 passed, 0 total
Time:        3.11s

如果您曾經(jīng)使用過 Jasmine 或其他測試框架,Jest允許我們使用describe和it來嵌套測試。您使用多少嵌套取決于您。我喜歡嵌套我的測試,這樣所有傳遞給describe和it的描述字符串幾乎就像一個句子一樣。

當(dāng)涉及到實際斷言時,您需要將要測試的內(nèi)容包裝在expect()調(diào)用中,然后在其上調(diào)用斷言。在這種情況下,我們使用了toBe。您可以在Jest文檔中找到所有可用斷言的列表。toBe使用===來檢查給定值是否與測試的值匹配。通過本教程,我們將遇到一些Jest的斷言。

測試業(yè)務(wù)邏輯

我們將測試我們的第一個狀態(tài)函數(shù)toggleDone。 toggleDone接收當(dāng)前狀態(tài)和我們想要切換的todo的ID。每個todo都有一個完成屬性,而toggleDone應(yīng)該將其從true切換為false,反之亦然。 注意:如果您正在跟隨本文,確保已經(jīng)克隆了代碼庫,并將app文件夾復(fù)制到包含您的__tests__文件夾的同一目錄中。您還需要安裝所有應(yīng)用程序的依賴項(例如React)。在克隆存儲庫后運行npm install即可確保全部安裝完成。

我將從app/state-functions.js導(dǎo)入函數(shù)并設(shè)置測試的結(jié)構(gòu)開始。當(dāng)Jest允許您使用describeit進行嵌套時,您也可以使用test,這通常更易于閱讀。test只是Jest it函數(shù)的別名,但有時可以使測試更易于閱讀,減少嵌套。例如,以下是我如何使用嵌套的describeit調(diào)用編寫該測試的方法:

import { toggleDone } from '../app/state-functions';
describe('toggleDone', () => {
  describe('when given an incomplete todo', () => {
    it('marks the todo as completed', () => {
    });
  });
});

這是test用法:

import { toggleDone } from '../app/state-functions';
test('toggleDone completes an incomplete todo', () => {
});

測試仍然很容易讀懂,但現(xiàn)在縮進少了一些。這主要取決于個人喜好;選擇您更喜歡的風(fēng)格即可。

現(xiàn)在我們可以編寫斷言了。首先,我們將創(chuàng)建我們的起始狀態(tài),然后將其傳遞到toggleDone中,以及我們要切換的todo的ID。toggleDone將返回我們的最終狀態(tài),然后我們可以對其進行斷言:

import { toggleDone } from "../app/state-functions";
test("tooggleDone completes an incomplete todo", () => {
  const startState = [{ id: 1, done: false, text: "Buy Milk" }];
  const finState = toggleDone(startState, 1);
  expect(finState).toEqual([{ id: 1, done: true, text: "Buy Milk" }]);
});

現(xiàn)在我使用toEqual進行斷言。您應(yīng)該使用toBe來測試原始值(例如字符串和數(shù)字),使用toEqual測試對象和數(shù)組。toEqual是專門用于處理數(shù)組和對象的,并且會遞歸檢查給定對象內(nèi)的每個字段或項目以確保其匹配。

有了這個,我們現(xiàn)在可以運行npm test并看到我們的狀態(tài)函數(shù)測試通過:

PASS  __tests__/state-functions.test.js
  ? tooggleDone completes an incomplete todo (9ms)
Test Suites: 1 passed, 1 total
Tests:       1 passed, 1 total
Snapshots:   0 passed, 0 total
Time:        3.166s

配置熱更新

在更改測試文件后,手動再次運行npm test有點繁瑣。 Jest最好的功能之一是其監(jiān)視模式,它會監(jiān)視文件更改并相應(yīng)地運行測試。它甚至可以根據(jù)更改的文件確定要運行的子集測試。它非常強大和可靠,您可以在監(jiān)視模式下運行Jest,并在整天編寫代碼時保留它。

要在監(jiān)視模式下運行它,您可以運行npm test -- watch。在第一個--之后傳遞給npm test的任何內(nèi)容都將直接傳遞給基礎(chǔ)命令。這意味著這兩個命令是等效的:

  • npm test -- --watch
  • jest --watch

我建議您在另一個終端窗口中將Jest保留運行,以便在本教程的其余部分中使用。

在繼續(xù)測試React組件之前,我們將在另一個狀態(tài)函數(shù)上編寫一個測試。在實際應(yīng)用程序中,我會編寫更多的測試,但是為了本教程的緣故,我將跳過其中一些?,F(xiàn)在,讓我們編寫一個測試,以確保我們的deleteTodo函數(shù)正常工作。在查看下面我的編寫方式之前,請嘗試自己編寫它并查看您的測試與我的測試有何不同。

請記住,您需要更新頂部的導(dǎo)入語句以導(dǎo)入deleteTodotoggleTodo

import { toggleDone, deleteTodo } from "../app/state-functions";

這是我編寫測試用例:

test('deleteTodo deletes the todo it is given', () => {
  const startState = [{ id: 1, done: false, text: 'Buy Milk' }];
  const finState = deleteTodo(startState, 1);
  expect(finState).toEqual([]);
});

這個測試與第一個測試并沒有太大的區(qū)別:我們設(shè)置起始狀態(tài),運行我們的函數(shù),然后對最終狀態(tài)進行斷言。如果您已在監(jiān)視模式下運行Jest,請注意它如何檢測到您的新測試并運行它,以及它運行速度的快速性!這是一種在寫測試時立即得到反饋的好方法。

上面的測試還演示了測試的過程,其中包括:

  • 設(shè)置
  • 執(zhí)行要測試的功能
  • 對結(jié)果進行斷言

通過以這種方式布局測試,您會發(fā)現(xiàn)更容易跟蹤和處理它們。

現(xiàn)在我們已經(jīng)滿意測試我們的狀態(tài)函數(shù),讓我們繼續(xù)測試React組件。

測試 React 組件

值得注意的是,默認情況下,我實際上鼓勵您不要在React組件上編寫太多測試。您想要非常徹底測試的任何內(nèi)容,例如業(yè)務(wù)邏輯,都應(yīng)該從組件中提取出來并作為獨立的函數(shù)存在,就像我們之前測試的狀態(tài)函數(shù)一樣。盡管如此,有時測試一些React交互(例如,確保用戶單擊按鈕時調(diào)用特定函數(shù)并傳遞正確參數(shù))是很有用的。我們將從測試我們的React組件是否呈現(xiàn)正確的數(shù)據(jù)開始,然后再看看如何測試交互。

為了編寫測試,我們將安裝Enzyme,這是由Airbnb編寫的包裝庫,使測試React組件變得更加容易。

注意:自本文首次編寫以來,React團隊已經(jīng)轉(zhuǎn)向Enzyme,并推薦使用[React Testing Library(RTL)](https://testing-library.com/docs/react-testing-library/intro)。閱讀該頁面很值得一看。如果您正在維護已經(jīng)使用Enzyme測試的代碼庫,則無需放棄所有內(nèi)容并轉(zhuǎn)移,但對于新項目,我建議考慮RTL。

除了Enzyme之外,我們還需要安裝適用于我們使用的React版本的適配器。對于React v16,使用enzyme-adapter-react-16,但對于React v17,目前沒有官方適配器可用,因此我們必須使用非官方版本。請注意,該軟件包旨在作為臨時措施,直到正式支持發(fā)布,并將在那時被棄用。

npm install --save-dev enzyme @wojtekmaj/enzyme-adapter-react-17

我們需要對 Enzyme 進行少量設(shè)置。在項目的根目錄中,創(chuàng)建setup-tests.js以下代碼并將其放入其中:

import { configure } from 'enzyme';
import Adapter from '@wojtekmaj/enzyme-adapter-react-17';
configure({ adapter: new Adapter() });

然后,我們需要告訴Jest在執(zhí)行任何測試之前為我們運行此文件。我們可以通過配置setupFilesAfterEnv選項來實現(xiàn)這一點。您可以將Jest配置放在自己的文件中,但我喜歡使用package.json并將東西放在jest對象中,Jest也會自動檢測到它:

"jest": {
  "setupFilesAfterEnv": [
    "./setup-tests.js"
  ]
}

現(xiàn)在我們準(zhǔn)備編寫一些測試了!讓我們測試該Todo組件是否在段落內(nèi)呈現(xiàn)其待辦事項的文本。首先我們將創(chuàng)建__tests__/todo.test.js并導(dǎo)入我們的組件:

import Todo from '../app/todo';
import React from 'react';
import { mount } from 'enzyme';
test('Todo component renders the text of the todo', () => {
});

Enzyme導(dǎo)入了mount。mount函數(shù)用于呈現(xiàn)我們的組件,然后允許我們檢查輸出并對其進行斷言。即使我們在Node中運行測試,我們?nèi)匀豢梢跃帉懶枰狣OM的測試。這是因為Jest配置了jsdom,一個在Node中實現(xiàn)DOM的庫。這很好,因為我們可以編寫基于DOM的測試,而無需每次啟動瀏覽器進行測試。

可以使用mount來創(chuàng)建我們的Todo

const todo = { id: 1, done: false, name: 'Buy Milk' };
const wrapper = mount(
  <Todo todo={todo} />
);

然后,我們可以調(diào)用wrapper.find,給它一個CSS選擇器,以查找我們希望包含Todo文本的段落。這個API可能會讓您想起jQuery,這是有意設(shè)計的。這是一個在渲染的輸出中搜索匹配元素的非常直觀的API。

const p = wrapper.find('.toggle-todo');

最后,我們可以斷言其中的文本是Buy Milk

expect(p.text()).toBe('Buy Milk');

完整的測試用例是這樣的:

import Todo from '../app/todo';
import React from 'react';
import { mount } from 'enzyme';
test('TodoComponent renders the text inside it', () => {
  const todo = { id: 1, done: false, name: 'Buy Milk' };
  const wrapper = mount(
    <Todo todo={todo} />
  );
  const p = wrapper.find('.toggle-todo');
  expect(p.text()).toBe('Buy Milk');
});

現(xiàn)在我們有了一個測試,可以檢查我們是否成功地渲染了todos。 接下來,讓我們看一下如何使用Jest的spy功能來斷言具有特定參數(shù)的函數(shù)被調(diào)用。在我們的情況下很有用,因為我們有一個Todo組件,它被賦予了兩個函數(shù)作為屬性,當(dāng)用戶單擊按鈕或執(zhí)行交互時應(yīng)該調(diào)用這些函數(shù)。

在這個測試中,我們將斷言當(dāng)Todo被單擊時,組件將調(diào)用它所賦予的doneChange屬性:

test('Todo calls doneChange when todo is clicked', () => {
});

我們希望有一個可以用來跟蹤其調(diào)用及其調(diào)用參數(shù)的函數(shù)。然后,我們可以檢查當(dāng)用戶單擊Todo時,doneChange函數(shù)是否被調(diào)用,并且被調(diào)用時使用了正確的參數(shù)。幸運的是,Jest在功能上提供了這個功能來使用spy(間諜)。spy是一種函數(shù),其實現(xiàn)方式并不重要,您只需要關(guān)心它何時以及如何被調(diào)用??梢詫⑵湎胂鬄槟趥刹煸摵瘮?shù)。要創(chuàng)建一個spy,我們調(diào)用jest.fn()

const doneChange = jest.fn();

這提供了一個函數(shù),我們可以對其進行監(jiān)視并確保其被正確調(diào)用。讓我們從使用正確的props來呈現(xiàn)我們的Todo開始:

const todo = { id: 1, done: false, name: 'Buy Milk' };
const doneChange = jest.fn();
const wrapper = mount(
  <Todo todo={todo} doneChange={doneChange} />
);

接下來,我們可以再次查找我們的段落,就像在前面的測試中一樣:

const p = wrapper.find(".toggle-todo");

然后我們可以調(diào)用simulate它來模擬用戶事件,并click作為參數(shù)傳遞:

p.simulate('click');

現(xiàn)在我們只需要斷言我們的spy函數(shù)是否被正確調(diào)用。在這種情況下,我們期望它被調(diào)用時使用了ID為1的todo。我們可以使用expect(doneChange).toBeCalledWith(1)來斷言這一點,然后我們的測試就完成了!

test('TodoComponent calls doneChange when todo is clicked', () => {
  const todo = { id: 1, done: false, name: 'Buy Milk' };
  const doneChange = jest.fn();
  const wrapper = mount(
    <Todo todo={todo} doneChange={doneChange} />
  );
  const p = wrapper.find('.toggle-todo');
  p.simulate('click');
  expect(doneChange).toBeCalledWith(1);
});

結(jié)論

Facebook很久以前就發(fā)布了Jest,但最近已經(jīng)被廣泛采用和改進。它已經(jīng)快速成為JavaScript開發(fā)人員的首選,而且它只會變得更好。如果你以前嘗試過Jest并且不喜歡它,我無法足夠地鼓勵你再次嘗試它,因為現(xiàn)在它基本上是一個完全不同的框架。它快速,重復(fù)運行規(guī)格非常出色,提供了出色的錯誤消息,并且有一個出色的表達式API,用于編寫良好的測試。

以上就是詳解如何使用Jest測試React組件的詳細內(nèi)容,更多關(guān)于Jest測試React組件的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • React?Fiber原理深入分析

    React?Fiber原理深入分析

    Fiber可以理解為一個執(zhí)行單元,每次執(zhí)行完一個執(zhí)行單元,React?Fiber就會檢查還剩多少時間,如果沒有時間則將控制權(quán)讓出去,然后由瀏覽器執(zhí)行渲染操作,這篇文章主要介紹了React?Fiber架構(gòu)原理剖析,需要的朋友可以參考下<BR>
    2023-01-01
  • ios原生和react-native各種交互的示例代碼

    ios原生和react-native各種交互的示例代碼

    本篇文章主要介紹了ios原生和react-native各種交互的示例代碼,非常具有實用價值,需要的朋友可以參考下
    2017-08-08
  • Rect Intersection判斷兩個矩形是否相交

    Rect Intersection判斷兩個矩形是否相交

    這篇文章主要為大家介紹了Rect Intersection判斷兩個矩形是否相交的算法詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2023-06-06
  • React精髓!一篇全概括小結(jié)(急速)

    React精髓!一篇全概括小結(jié)(急速)

    這篇文章主要介紹了React精髓!一篇全概括小結(jié)(急速),小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2019-05-05
  • 在Ant Design Pro登錄功能中集成圖形驗證碼組件的方法步驟

    在Ant Design Pro登錄功能中集成圖形驗證碼組件的方法步驟

    這篇文章主要介紹了在Ant Design Pro登錄功能中集成圖形驗證碼組件的方法步驟,這里的登錄功能其實就是一個表單提交,實現(xiàn)起來也很簡單,具體實例代碼跟隨小編一起看看吧
    2021-05-05
  • 詳解React中的this指向

    詳解React中的this指向

    這篇文章主要介紹了React中的this指向的相關(guān)資料,幫助大家更好的理解和學(xué)習(xí)使用React,感興趣的朋友可以了解下
    2021-04-04
  • 一文詳解React?Redux使用方法

    一文詳解React?Redux使用方法

    這篇文章主要介紹了一文詳解React?Redux使用方法,文章圍繞主題展開詳細的內(nèi)容戒殺,具有一定的參考價值,需要的小伙伴可以參考一下
    2022-09-09
  • React18系列reconciler從0實現(xiàn)過程詳解

    React18系列reconciler從0實現(xiàn)過程詳解

    這篇文章主要介紹了React18系列reconciler從0實現(xiàn)過程詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2023-01-01
  • react native基于FlatList下拉刷新上拉加載實現(xiàn)代碼示例

    react native基于FlatList下拉刷新上拉加載實現(xiàn)代碼示例

    這篇文章主要介紹了react native基于FlatList下拉刷新上拉加載實現(xiàn)代碼示例
    2018-09-09
  • react組件實例屬性props實例詳解

    react組件實例屬性props實例詳解

    這篇文章主要介紹了react組件實例屬性props,本文結(jié)合實例代碼給大家簡單介紹了props使用方法,代碼簡單易懂,需要的朋友可以參考下
    2023-01-01

最新評論