Jest使用筆記
簡介
- 是一個由Facebook開發的JavaScript單元測試框架
- 單元測試(Unit Test):針對程式中的最小單元進行測試
- 主要對於function進行測試,是否符合預期運行結果
環境建置
使用npm安裝
npm install --save-dev jest
- 在package.json檔案中增加指令
- 可以在終端機輸入 npm run test 來執行jest測試
{ "scripts": { "test": "jest" }}// 查看測試覆蓋率{ "scripts": { "test": "jest --coverage" }}
設定配置文件
- 輸入指令生成
jest.config
檔案 - 在jest 29.7版中,已經可以直接使用ES6語法,不需另外安裝Babel
npm init jest@latest
- 會問一些配置問題,根據需求選擇
ps: 測試環境差別
- Node (testEnvironment: 'node')
- 適合 Node.js 應用程序和伺服器端代碼提供的環境
- 沒有 DOM 相關的全局變數(例如 window 或 document)
- 最適合測試純 Node.js 代碼,例如服務器端邏輯
- JSDOM (testEnvironment: 'jsdom')
- 是一個用 JavaScript 實現的 DOM 模擬器
- 提供 DOM 相關的全局變數,像是 window 或 document
- 可以在 Node.js 環境中模擬瀏覽器的行為,並測試那些與 DOM 互動的代碼
- 最適合測試前端代碼,例如 React 或 Vue 組件
基本用法
1. 建立一個js檔案
- 撰寫需要使用的function
- 使用
module.exports
把function輸出
// sum.jsfunction sum(a, b) { return a + b;}module.exports = sum;
2. 建立一個test.js檔案
- 使用
require
引入要測試的function
//sum.test.jsconst sum = require('./sum');test('測試 8+9 會等於17', () => { expect(sum(8, 9)).toBe(17); // passed});
3. 基本語法
- test / it:定義一個單元測試
test('該測試的說明', () => { expect(要測試的function).toBe(預期的結果)})it('該測試的說明', () => { expect(要測試的function).toBe(預期的結果)})
- describe:定義群組單元測試,裡面可以放多個test
describe('測試加法函式', () => { test('測試 8+9 會等於17', () => { expect(sum(8, 9)).toBe(17); }); test('測試 1+1 會等於2', () => { expect(sum(1, 1)).toBe(2); });});
🍞 Modifiers
- not:用於表示否定
expect(1 + 2).not.toBe(4)
- resolves:檢查一個 promise 是否成功
const promise = Promise.resolve('success');expect(promise).resolves.toBe('success');
- rejects:檢查一個 promise 是否失敗
const promise = Promise.reject(new Error('failure'));expect(promise).rejects.toThrow('failure');
🍞 常用的Matchers
- toBe:使用Object.is來比較是否相等,常用於原始型別
- toEqual:進行深層次的值比較,適用於Object和Array的比較
test('object assign',() => { const a = {} expect(a).toBe({}) // failed expect(a).toEqual({}) // passed})
- toBeTruthy:檢查值是否為 truthy
- toBeFalsy:檢查值是否為 falsy
describe('truthy or falsey' ,() => { test('truthy', () => { expect('Hello').toBeTruthy(); }); test('falsey', () => { expect(0).toBeFalsy(); });})
- toContain:檢查陣列是否包含某個特定元素
expect(['apple', 'banana', 'cherry']).toContain('banana');
- toThrow: 檢查函數是否拋出錯誤
const throwFunction = () => { throw new Error('error!');};expect(throwFunction).toThrow('error!');
Number的比較
- toBeGreaterThan
- toBeGreaterThanOrEqual
- toBeLessThan
- toBeLessThanOrEqual
describe('numbers', () => { const value = 8 + 9; test('8加9', () => { expect(value).toBe(17); expect(value).toBeGreaterThan(16); expect(value).toBeLessThan(21); expect(value).toBeLessThanOrEqual(18); });});
🍞 非同步函式測試
- 在node環境安裝axios
- 取得一個todo測試
// async.jsconst axios = require('axios');const fetchData = async (id) => { const res = await axios.get(`https://jsonplaceholder.typicode.com/todos/${id}`); return res.data;};module.exports = fetchData;
- 因為是非同步行為,要加上async…await
const fetchData = require('./async');test('it should return a todo', async () => { const todo = await fetchData(1); expect(todo.id).toBe(1);});
🍞 常在群組測試使用的方法
- beforeEach: 在每一個單元測試之前執行
- afterEach: 在每一個單元測試之後執行
- beforeAll: 在所有單元測試之前執行一次
- afterAll: 在所有單元測試之後執行一次
- 寫在describe內,表示該組測試才會用到
// 使用 beforeEach 和 afterEachlet counter = 0;describe("Counter Tests", () => { beforeAll(() => { console.log('測試開始了') }); afterAll(() => { console.log('測試結束囉') }) beforeEach(() => { counter = 0; }); afterEach(() => { console.log(`Counter after test: ${counter}`); }); test("Increment counter", () => { counter++; expect(counter).toBe(1); }); test("Decrement counter", () => { counter--; expect(counter).toBe(-1); });});
4. Mock用法
- 可以不受外部依賴(資料庫 , API…),單純模擬測試功能
- jest.fn:創建模擬函式
const mockFn = jest.fn(scalar => 42 + scalar);mockFn(0); // 42mockFn(1); // 43
- mockReturnValue:設定回傳的值
const mockFn = jest.fn();mockFn.mockReturnValue(123);expect(mockFunction()).toBe(123);
- mockReturnValueOnce:只回傳一次,用於在連續調用中回傳不同的值
const mockFn = jest.fn();mockFn .mockReturnValueOnce('first call') .mockReturnValueOnce('second call');// 首次調用expect(mockFunction()).toBe('first call');// 第二次調用expect(mockFunction()).toBe('second call');
- jest.spyOn:用於偵測某物件的某方法是否被調用,也可以使用它來模擬方法的返回值或行為
- 使用
jest.spyOn(axios, 'get')
來創建一個觀察axios
的get
方法的"間諜" - 這個"間諜"會攔截所有對
axios.get
的調用,並對它進行記錄 - 使用
.mockReturnValueOnce()
方法來模擬axios.get
在下一次調用時的返回值
// asynctest.test.jsconst fetchData = require('./async');const axios = require('axios')// 模擬axios.gettest('mock axios', async () => { const spy = jest.spyOn(axios, 'get').mockReturnValueOnce({ data: { id: 1, todo: 'Do Homework!', }, }); const res = await fetchData(1); expect(res.todo).toBe('Do Homework!'); spy.mockRestore();});
參考資料
# JavaScript # Unit Test