單元測試主要包含斷言、測試框架、測試用例、測試覆蓋率、mock、持續集成等幾個方面,因爲Node的特殊性,它還會加入異步代碼測試和私有方法的測試這兩個部分。html
在程序設計中,斷言是一種放在程序中的一階邏輯(如一個結果爲真或是假的邏輯判斷式),目的是爲了標示程序開發者預期的結果——當程序運行到斷言的位置時,對應的斷言應該爲真。若斷言不爲真,程序會停止運行,並出現錯誤信息。node
斷言用於檢查程序在運行時是否知足指望。ios
node自帶斷言就是assert模塊,具體使用請查看官方文檔:地址npm
const assert = require('assert');
assert.equal(Math.max(1, 100), 100);
複製代碼
經常使用的第三方斷言庫有chai,官方地址:連接json
前面提到斷言一旦檢查失敗,將會拋出異常中止整個應用,這對於作大規模斷言檢查時並不友好。更通用的作法是,記錄下拋出的異常並繼續執行,最後生成測試報告。這些任務的承擔者就是測試框架。axios
經常使用的第三方測試框架有mocha,jest,他們之間的區別在於jest內容更加全面,集成了斷言,jsdom模擬瀏覽器DOM環境。api
每一個功能至少要包含一個測試用例,今天介紹jest寫測試用例,先安裝jest和@types/jest,後面這個是類型聲明文件,能夠幫助咱們在寫代碼的時候會有語法提示。promise
npm i jest @types/jest
複製代碼
默認會測試spec和test結尾的js文件,全部寫單元測試的文件名必須是sum.spec.js或者sum.test.js這個的格式。瀏覽器
而後須要在package.json裏面增長一段腳本bash
{
"scripts": {
"test": "jest"
}
}
複製代碼
經過運行npm run test
最後會生成測試報告
在測試用例中使用it
語法表示一個用例,expect
表示預期結果,toBe
表示三個等號的比較,若是條件成立單元測試便可經過。
至關,不相等,包含,等等,匹配的關係
// describe表示分組,分組裏面一個個的用例
describe('測試基本方法', () => {
it('測試sum函數', () => {
expect(sum(1, 2)).toBe(3)
})
it('測試1+1=2', () => {
expect(1 + 1).toBe(2)
})
it ('對象比較', () => {
expect({name: 1}).toEqual({name: 1})
})
})
it('測試不相等', () => {
expect(1+1).not.toBe(3) // 1+1不等3
expect(3).toBeLessThan(5) // 3<5
})
it('測試包含', () => {
expect('hello').toContain('h') // 參數是字符串
expect('hello').toMatch(/h/) // 參數能夠是正則
})
複製代碼
it('測試刪除DOM', () => {
document.body.innerHTML = `<div><button></button></div>`
let button = document.querySelector('button')
expect(button).not.toBe(null)
// 本身寫的移除的DOM方法
removeNode(button);
button = document.querySelector('button')
expect(button).toBe(null)
})
複製代碼
// 回調
export const getDataCallback = fn => {
setTimeout(() => {
fn({name: 'callback'})
}, 1000);
}
// promise
export const getDataPromise = () => {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve({name: 'promise'})
}, 1000);
})
}
複製代碼
import { getDataCallback, getDataPromise } from '../util'
// 異步回調
it('測試回調函數', (done) => {
// done參數
getDataCallback((data) => {
expect(data).toEqual({ name: 'callback' })
done() // 標識調用完成
})
})
it('測試promise', () => {
// 返回的promise會等待完成
return getDataPromise().then(data => {
expect(data).toEqual({ name: 'promise' })
})
})
it('測試promise', async () => {
// 使用await語法
const data = await getDataPromise()
expect(data).toEqual({ name: 'promise' })
})
複製代碼
若是咱們要測試接口,好比使用axios發送api請求
import axios from 'axios'
// 測試接口調用
export const fetchUser = () => {
return axios.get('/list')
}
複製代碼
咱們並不會真實的發送API請求,而是模擬數據返回,這個時候能夠在__mocks__
下面建axios.js
文件,jest就不會再使用node_modules文件中的axios發請求了,而是使用咱們本身寫的axios模塊。
// mock axios
export default {
get(url) {
return new Promise((resolve, reject) => {
// 根據請求路徑mock數據
if (url === '/list') {
resolve({ name: 'hello' })
}
})
}
}
複製代碼
import { fetchUser } from '../api'
it('測試請求列表', async () => {
// 把請求的邏輯mock
const data = await fetchUser()
expect(data).toEqual({name: 'hello'})
})
複製代碼
想要查看測試覆蓋率,咱們須要先生成配置文件,經過命令
npx jest --init
複製代碼
而後還須要在package.json中添加一段腳本
{
"scripts": {
"test": "jest --coverage"
}
}
複製代碼
經過命令運行npm run test
最後會生成測試覆蓋率
咱們將測試用例的不一樣組織方式稱爲測試風格,現今流行的單元測試風格主要有TDD(測試驅動開發)和BDD(行爲驅動開發)兩種。
關注點不一樣。