【React】使用Jest寫單元測試

閱讀時間約 15 分鐘

先前環境設定

在使用 Jest 前需要先使用 npm 安裝:

npm install jest

使用指令:

 npm jest

使用內容

先來看一下大致長得怎樣😃

這是Header.jsx

// Header.jsx
import React from "react";

const Header = ({ heading, subHeading }) => {
return (
<section className="header">
<h1 data-testid="heading">{heading}</h1>
<p data-testid="subHeading">{subHeading}</p>
</section>
);
};

export default Header;

在來,針對Header.jsx,所寫寫的unit test:

// Header.test.jsx

import { render, screen } from "@testing-library/react";
import Header from "../Header";

describe("test header component", () => {
test("render the heading text", () => {
render(<Header heading="Word Counter" />);
const heading = screen.getByTestId("heading");
expect(heading.innerHTML).toBe("Word Counter");
});
});

完蛋看不懂,先讀GPT針對基本名詞的解析:

describe 是 Jest 中的一個函數,用於組織測試案例。它可以幫助你將相關的測試案例分組在一起,提高可讀性和組織性。
test 是 Jest 提供的函數,用於撰寫單一測試案例。它接受兩個參數:測試案例的描述,以及一個包含測試程式碼的函數。
test 為測試的最小單位,就是像是變數的宣告一樣,要攥寫每一筆測試時都需要使用 test 宣告。
render 是 @testing-library/react 提供的函數,用於渲染 React 組件。我們使用 render 渲染 Header 組件並傳遞 heading 屬性為 "Word Counter"。
screen 是 @testing-library/react 提供的物件,用於查詢渲染結果中的元素。
getByTestId 是用於查詢帶有特定 data-testid 屬性的元素。
expect 是 Jest 提供的斷言函數,用於進行測試斷言。

這樣是不是可以大概知道,先指定我要render的東西<Header/>,接著使用getByTestId去依照ID指定我要搜尋的標籤。

expect(heading.innerHTML).toBe("Word Counter");

是指“expect(目標).toBe(應該出現的內容);”

🥰這樣是不是清楚很多了,那接下來,我先做了一個畫面:

raw-image

這是一個可以計算文字數跟字元數的動態JS,那在jsx是長這樣:

import React, { useRef, useState } from "react";

const Counter = () => {
// ...
return (
<section className="counter">
<textarea
// ...
data-testid="textArea"
placeholder="Type or paste your text"></textarea>
<button
// ...
onClick={handleButton}
data-testid="clearBtn"
>
Clear
</button>

<p className="result">
<span data-testid="charLength">Character: {charLength}</span>
<span data-testid="wordLength">Word: {wordLength}</span>
</p>
</section>
);
};

export default Counter;

那我接下來在裡面輸入東西:

raw-image

針對這一項功能,我可以寫一隻測試如下:

import { render, screen } from "@testing-library/react";
import "@testing-library/jest-dom";
import Counter from "../Counter";
import userEvent from "@testing-library/user-event";

test("change textarea and update result", () => {
render(<Counter />);
const textArea = screen.getByTestId("textArea");
const charLength = screen.getByTestId("charLength");
const wordLength = screen.getByTestId("wordLength");

// 模擬為東西進去
userEvent.type(textArea, "test123");
expect(charLength.innerHTML).toBe("Character: 7");
expect(wordLength.innerHTML).toBe("Word: 1");
});

去模擬我輸入“test123”,他應該要輸出什麼樣的內容。

那如果我想繼續:當我按下“clear“,裡面東西,字元數,文字數全部清空,那我就可以這樣寫:

import { render, screen } from "@testing-library/react";
import "@testing-library/jest-dom";
import Counter from "../Counter";
import userEvent from "@testing-library/user-event";

test("clear change textarea and update result", () => {
render(<Counter />);
const textArea = screen.getByTestId("textArea");
const charLength = screen.getByTestId("charLength");
const wordLength = screen.getByTestId("wordLength");
const clearBtn = screen.getByTestId("clearBtn");

userEvent.click(clearBtn);
// 模擬案”click",後會誒出現的內容
expect(charLength.innerHTML).toBe("Character: 0");
expect(wordLength.innerHTML).toBe("Word: 0");
});


那如果是碰到fetch的測試,就是增加async跟waitFor:

import { getByTestId, render, waitFor } from "@testing-library/react";
import Joke from "../Joke";

describe("test joke component", async () => {
test("render joke test", () => {
render(<Joke />);
const jokeHeadline = getByTestId("jokeHeadline");
await waitFor(() => {
expect(jokeHeadline.innerHTML).toBeTruthy();
});
});
}); 


🙂接下來,介紹wrapper:

一樣先看GPT的解釋:

以下是 wrapper 的用法和目的:

- 包裹渲染組件: 在測試中,你通常會使用測試工具庫提供的函數(如 Enzyme 的 shallow 或 mount,Vue Test Utils 的 mount)來渲染組件。這些函數將組件渲染成虛擬 DOM,同時返回一個稱為 wrapper 的對象,它代表著包裹了渲染結果的容器。

- 查詢、操作和斷言: wrapper 對象通常提供了許多方法,這些方法讓你能夠查詢虛擬 DOM 中的元素、訪問組件的屬性和狀態,甚至模擬用戶互動。你可以使用這些方法來進行斷言、操作元素,並驗證組件的行為是否符合預期。

- 斷言測試結果: 通過 wrapper,你可以斷言組件的渲染結果是否與預期相符。你可以使用 wrapper 提供的方法查詢特定的元素,然後使用斷言方法(如 Jest 的 expect)來驗證渲染結果是否符合預期。

總之,wrapper 是一個用於包裹渲染組件並提供測試工具庫所需方法的對象。它使你能夠進行測試,驗證組件的渲染、行為和狀態是否如預期。請注意,wrapper 的用法和方法可能因測試工具庫而異,所以具體的實現方式可能會根據你使用的工具庫有所不同。

講那麼多,其實大概可以看出來是做來渲染的。
舉例來說,像是我們在使用router的情境下:

function App() {
return (
<div className="App">
<Routes>
<Route path="/" element={<HomePage />} />
<Route path="/joke" element={<JokePage />} />
<Route path="*" element={<PageNotFound />} />
</Routes>
</div>
);
}

export default App;

如果我要針對PageNotFound去寫測試:

import { render } from "@testing-library/react";
import PageNotFound from "../PageNotFound";
import { BrowserRouter } from "react-router-dom";

describe("test PageNotFound Page", () => [
test("render text and image", () => {
// 因為PageNotFound有被BrowserRouter渲染過,因此要在render中增加wrapper參數
const { getByTestId, getByAltText } = render(<PageNotFound />, {
wrapper: BrowserRouter,
});
const pnfText = getByTestId("pnfText");
expect(pnfText.innerHTML).toBe("Oops - Page Not Found!");
}),
]);
4會員
10內容數
留言0
查看全部
發表第一個留言支持創作者!
你可能也想看
Google News 追蹤
Thumbnail
這個秋,Chill 嗨嗨!穿搭美美去賞楓,裝備款款去露營⋯⋯你的秋天怎麼過?秋日 To Do List 等你分享! 秋季全站徵文,我們準備了五個創作主題,參賽還有機會獲得「火烤兩用鍋」,一起來看看如何參加吧~
Thumbnail
美國總統大選只剩下三天, 我們觀察一整週民調與金融市場的變化(包含賭局), 到本週五下午3:00前為止, 誰是美國總統幾乎大概可以猜到60-70%的機率, 本篇文章就是以大選結局為主軸來討論近期甚至到未來四年美股可能的改變
Thumbnail
Faker昨天真的太扯了,中國主播王多多點評的話更是精妙,分享給各位 王多多的點評 「Faker是我們的處境,他是LPL永遠繞不開的一個人和話題,所以我們特別渴望在決賽跟他相遇,去直面我們的處境。 我們曾經稱他為最高的山,最長的河,以為山海就是盡頭,可是Faker用他28歲的年齡...
Thumbnail
React 表單驗證是一種技術與使用者體驗的設計,讓使用者能夠即時檢查輸入的資料並修正,提升使用者的使用體驗,並確保資料的正確性。
Thumbnail
近日,歐盟官方公報發佈了法規(EU)2023/1132,對REACH法規 (EC) No 1907/2006 附件XVII限制物質清單進行修訂,以適應CLP法規的最新變化。 根據附件XVII中第28、29和30條,被歸類為致癌、致突變、致生殖毒性(CMR)1A類和1B類的物質,禁止投放於市場或供應普
Thumbnail
useContext 是一種 React hook,讓我們能夠直接取用其他元件的 Context,而無須層層傳遞 props,進而使程式碼簡潔易讀。
Thumbnail
前言 嗨,各位懷舊遊戲愛好者!今天要跟大家分享一個有趣的主題:如何利用React和Pixi.js這兩大神兵利器,重塑我們那個年代的經典紅白機打磚塊遊戲! 先跟大家簡單科普一下,React是一個超級火爆的前端框架,能讓我們輕鬆創建可重用的UI組件,組件間的狀態管理也相當方便。。。
Thumbnail
想要知道如何用最新技術來製作一個App嗎? 跟著JayLin用React | Redux Tool Kit | TypeScript | TailwildCSS 來製作一個Drawing App
Thumbnail
React Hook onclick call a callback function with params, and change css style example: 本筆記參考: 1. https://www.codegrepper.com/code-examples/javascrip
Thumbnail
Create React App 提供了快速建立React App環境的方法: 1. 安裝node.js 2. 建立React project: $ npx create-react-app my-app 3. 啟動app $ cd my-app $ npm start npm start之後即打
Thumbnail
接續上一篇,navbar元件其實寫的不是很好,還不能說是可真正reuse,我們把程式改成這樣,透過props傳入navbar的items,定義好navbar title, li的href/name/active等等,就可以達到navbar元件無須改code就能重用的目的! Navbar 元件中用m
Thumbnail
接續上一篇,這邊要來寫一個React hello world app,最後安裝webpack-dev-server來提升開發效率。 使用npm安裝react, react-dom: $ npm install react react-dom --save dependencies下紀錄的是生產環境會
Thumbnail
React開發有兩種方式,一種是使用CDN方式include react的官方lib,然後使用babel來將JSX編譯成瀏覽器看得懂的javascript。 但是在react中還會使用到sass, scss等等,還需要額外編譯成css瀏覽器才看得懂。 而webpack的誕生,就是為了解決上述的問題,
Thumbnail
這個秋,Chill 嗨嗨!穿搭美美去賞楓,裝備款款去露營⋯⋯你的秋天怎麼過?秋日 To Do List 等你分享! 秋季全站徵文,我們準備了五個創作主題,參賽還有機會獲得「火烤兩用鍋」,一起來看看如何參加吧~
Thumbnail
美國總統大選只剩下三天, 我們觀察一整週民調與金融市場的變化(包含賭局), 到本週五下午3:00前為止, 誰是美國總統幾乎大概可以猜到60-70%的機率, 本篇文章就是以大選結局為主軸來討論近期甚至到未來四年美股可能的改變
Thumbnail
Faker昨天真的太扯了,中國主播王多多點評的話更是精妙,分享給各位 王多多的點評 「Faker是我們的處境,他是LPL永遠繞不開的一個人和話題,所以我們特別渴望在決賽跟他相遇,去直面我們的處境。 我們曾經稱他為最高的山,最長的河,以為山海就是盡頭,可是Faker用他28歲的年齡...
Thumbnail
React 表單驗證是一種技術與使用者體驗的設計,讓使用者能夠即時檢查輸入的資料並修正,提升使用者的使用體驗,並確保資料的正確性。
Thumbnail
近日,歐盟官方公報發佈了法規(EU)2023/1132,對REACH法規 (EC) No 1907/2006 附件XVII限制物質清單進行修訂,以適應CLP法規的最新變化。 根據附件XVII中第28、29和30條,被歸類為致癌、致突變、致生殖毒性(CMR)1A類和1B類的物質,禁止投放於市場或供應普
Thumbnail
useContext 是一種 React hook,讓我們能夠直接取用其他元件的 Context,而無須層層傳遞 props,進而使程式碼簡潔易讀。
Thumbnail
前言 嗨,各位懷舊遊戲愛好者!今天要跟大家分享一個有趣的主題:如何利用React和Pixi.js這兩大神兵利器,重塑我們那個年代的經典紅白機打磚塊遊戲! 先跟大家簡單科普一下,React是一個超級火爆的前端框架,能讓我們輕鬆創建可重用的UI組件,組件間的狀態管理也相當方便。。。
Thumbnail
想要知道如何用最新技術來製作一個App嗎? 跟著JayLin用React | Redux Tool Kit | TypeScript | TailwildCSS 來製作一個Drawing App
Thumbnail
React Hook onclick call a callback function with params, and change css style example: 本筆記參考: 1. https://www.codegrepper.com/code-examples/javascrip
Thumbnail
Create React App 提供了快速建立React App環境的方法: 1. 安裝node.js 2. 建立React project: $ npx create-react-app my-app 3. 啟動app $ cd my-app $ npm start npm start之後即打
Thumbnail
接續上一篇,navbar元件其實寫的不是很好,還不能說是可真正reuse,我們把程式改成這樣,透過props傳入navbar的items,定義好navbar title, li的href/name/active等等,就可以達到navbar元件無須改code就能重用的目的! Navbar 元件中用m
Thumbnail
接續上一篇,這邊要來寫一個React hello world app,最後安裝webpack-dev-server來提升開發效率。 使用npm安裝react, react-dom: $ npm install react react-dom --save dependencies下紀錄的是生產環境會
Thumbnail
React開發有兩種方式,一種是使用CDN方式include react的官方lib,然後使用babel來將JSX編譯成瀏覽器看得懂的javascript。 但是在react中還會使用到sass, scss等等,還需要額外編譯成css瀏覽器才看得懂。 而webpack的誕生,就是為了解決上述的問題,