Jest - 讓我先試試
基本的Jest語法練習紀錄
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.js
function sum(a, b) {
return a + b
}
module.exports = sum
2. 建立一個test.js檔案
- 使用
require引入要測試的function
//sum.test.js
const 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.js
const 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 和 afterEach
let 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) // 42
mockFn(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.js
const fetchData = require('./async')
const axios = require('axios')
// 模擬axios.get
test('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()
})