文章大綱
使用create react app創建專案的時候,你會發現它自動幫你安裝好testing-library的一些套件。
{
"dependencies": {
//...
"@testing-library/jest-dom": "^5.11.4",
"@testing-library/react": "^11.1.0",
"@testing-library/user-event": "^12.1.10",
}
因為我有使用craco,所以指令部分他也有幫你寫好script:
{
"scripts": {
//...
"test": "craco test"
}
}
在/src資料夾中會看到跟測試有關的兩個檔案:
// jest-dom adds custom jest matchers for asserting on DOM nodes.
// allows you to do things like:
// expect(element).toHaveTextContent(/react/i)
// learn more: https://github.com/testing-library/jest-dom
import "@testing-library/jest-dom";
import { render, screen } from '@testing-library/react';
import App from './App';
test('renders learn react link', () => {
render(<App />);
const linkElement = screen.getByText(/learn react/i);
expect(linkElement).toBeInTheDocument();
});
首先在create react app創建專案完成的情況下,直接跑:
$ yarn test
你可能會遇到一些錯誤,以下是我遇到的幾個:
如果有使用alias,會找不到相關路徑:
Cannot find module '@/XXX/XXX' from 'src/App.js'
要把jest的moduleNameMapper設定加上去。
像我是在craco.config.js中有加入alias,名稱叫做@
const path = require("path");
module.exports = {
//...
webpack: {
alias: {
"@": path.resolve(__dirname, "src/"),
},
},
};
所以在jest設定中也要叫做@
{
//...
"jest": {
"moduleNameMapper": {
"^@/(.+)": "<rootDir>/src/$1"
}
},
}
找不到matchMedia
這時候在setupTests.js加入以下這段:
import "@testing-library/jest-dom";
window.matchMedia = query => ({
matches: false,
media: query,
onchange: null,
addListener: jest.fn(), // deprecated
removeListener: jest.fn(), // deprecated
addEventListener: jest.fn(),
removeEventListener: jest.fn(),
dispatchEvent: jest.fn(),
});
App.test.js測試失敗
因為一開始create react app時,App.js的內容是預設的,裡面有react logo、一些預設文字。
App.test.js中的測試項目也是以預設的內容來測,當我們有改動App.js的內容,自然就會測試失敗拉!
import { render, screen } from "@testing-library/react";
import App from "./App";
test("renders learn react link", () => {
render(<App />);
const linkElement = screen.getByText(/learn react/i); // <-- 因為我App.js裡面已經沒有 "learn react"文字了,所以失敗。
expect(linkElement).toBeInTheDocument();
});
可以把他先簡易改成render就好:
import App from "./App";
import ReactDOM from "react-dom";
it("renders without crashing", () => {
const div = document.createElement("div");
ReactDOM.render(<App />, div);
});
接下來我們可以試著針對function來進行測試:
我在/utils資料夾中放有許多工具,例如日期formate、價錢format之類的,這邊先選一個來進行測試。
src/
- utils/
-- format.js
-- format.test.js //<--同層下新增測試檔案
export const dateFormat = date => {
return moment(date).isValid() && typeof date === "string"
? moment(date).format("YYYY-MM-DD HH:mm:ss")
: "is not valid date";
};
正式寫測試
import { dateFormat } from "./format";
describe("format functions", () => {
test("dateFormat", () => {
expect(dateFormat("2021-07-07T00:00:00+08:00")).toBe(`2021-07-07 00:00:00`);
});
});
先引入我寫好的function,
我預期我收到資料庫傳來的日期格式,我要轉換成一般人習慣閱讀的格式。
再次跑測試
$ yarn test
這時會看到這時會看到Test Suites有2個、Tests有兩個。

- Test Suites:表示我有兩隻
xxx.test.js檔案 - Tests:表示我有兩個測試(每個檔案裡各一個測試)
因為測試就是要確保各種可能性,所以通常expect不會只寫一種。
import { dateFormat } from "./format";
describe("format functions", () => {
test("dateFormat", () => {
expect(dateFormat("2021-07-07T00:00:00+08:00")).toBe(`2021-07-07 00:00:00`);
expect(dateFormat(null)).toBe(`is not valid date`);
expect(dateFormat(123)).toBe(`is not valid date`);
});
});
再來因為format.js中還有很多其他function,也可以寫在一起。
import { priceFormat, dateFormat } from "./format";
describe("format functions", () => {
test("priceFormat", () => {
expect(priceFormat({ val: 200, currency: 0 })).toBe(`¥ 2`);
});
test("dateFormat", () => {
expect(dateFormat("2021-07-07T00:00:00+08:00")).toBe(`2021-07-07 00:00:00`);
expect(dateFormat(null)).toBe(`is not valid date`);
expect(dateFormat(123)).toBe(`is not valid date`);
});
});
這樣就是最簡的最基本的測試流程拉!





發表評論
想要加入討論嗎?請盡情發表您的想法!