react 单元测试 (jest+enzyme)
為什么要做單元測試
作為一個前端工程師,我是很想去謝單元測試的,因為每天的需求很多,還要去編寫測試代碼,感覺時間都不夠用了。
不過最近開發(fā)了一個比較復雜的項目,讓我感覺一旦項目大了、復雜了,而且還是多人維護一個應用,編寫測試代碼,
還是很有必要的。畢竟這樣做完之后,后邊的維護會輕松很多。
單元測試
測試代碼的最小單元,一個函數(shù)就是一個單元
測試工具
主要用到的測試工具是 jest 和 enzyme
jest 、 enzyme 介紹
jest 是 facebook 發(fā)布的一個開源的,基于 jasmine 框架的 javascript 單元測試工具它提供了很多有效的功能,
包含了內(nèi)置的測試環(huán)境的 DOM API 來操作 Dom、斷言庫、mock 等功能,并且 jest 是 react 的官網(wǎng)上面推薦
的工具。
enzyme 是 Airbnb 開源的 react 測試類庫,提供了一套簡潔強大的 api ,可以通過 jq 的風格進行 dom 處理,
還可以引用一些其他的 dom 操作庫。
react 單元測試的搭建
react 項目是基于 webpack + babel 來進行構建的。
安裝 npm 包
首先需要添加一些 jest + enzyme 的 npm 包
yarn add jest enzyme babel-jest regenerator-runtime react-test-renderer
enzyme 需要安裝對應的 react 的 adapter 版本
yarn add enzyme-adapter-react-16
配置文件
1、package.json
"scripts": {
"test": "jest --colors --coverage"
},
添加顏色和現(xiàn)實覆蓋率
.babelrc 文件
"env": { // 單元測試下配置
"test": {
"presets": [
"react",
"react-optimize",
[
"env",
{
"modules": "commonjs", // 主要是添加這個
"debug": true,
"useBuiltIns": false,
"targets": {
"browsers": "defaults"
}
}
],
"stage-0"
]
}
}
因為測試環(huán)境的在 babel 中的配置 dev 為 test。
所以這里需要特殊配置,modules 的形式是 commonjs
添加jest配置文件jest.config
module.exports = {
roots: ['<rootDir>/__test__/', '<rootDir>/src/'], // 測試的目錄
modulePaths: ['<rootDir>'],
coveragePathIgnorePatterns: ['/node_modules/', '/tests/setup.js'], //忽略統(tǒng)計覆蓋率的文件
// bail: true,
// testRegex: '', // 后綴名稱
// testPathIgnorePatterns: 'est', // 忽略路徑
// moduleNameMapper: { // 與測試無關的資源文件同意mock 掉,這樣在import 的時候就不會真的引入這些文件
// '^import?': '<rootDir>/build/jestImportMock.js',
// '\.(css|less|gif|jpg|jpeg|png)$': '<rootDir>/build/jestStyleMock.js',
// },
};
jest 詳解
1、簡單測試結構
function sum(a,b){
return a+b;
}
it('adds 1 + 2 to equal 3', () => {
expect(sum(1, 2)).toBe(3);
});
2、異步的測試結構
async function sum (a,b){
return a+b;
}
it('adds 1 + 2 to equal 3',async () => {
const total = await sum(1,2)
expect(total).toBe(3);
});
3、Mock Function 結構
function forEach(items, callback) {
for (let index = 0; index < items.length; index++) {
callback(items[index]);
}
}
const mockCallback = jest.fn(x => 42 + x);
forEach([0, 1], mockCallback);
// 可以 mockCallback.mock 訪問 mockCallback 狀態(tài)
1、jest.fn 用來創(chuàng)建一個 mock function
2、mockCallback.mock 可以訪問 mock function 的狀態(tài)
mock 的屬性:
calls : 調(diào)用的參數(shù)數(shù)組,保存了每次調(diào)用的入?yún)?/p>
calls.length : 調(diào)用次數(shù)
calls[0][0] : 第一次調(diào)用的時候的第一個參數(shù)
results:調(diào)用的結果數(shù)組
results[0].value : 第一次調(diào)用的返回結果
執(zhí)行 mock function
const myMock = jest.fn();
console.log(myMock());
// > undefined
myMock
.mockReturnValueOnce(10)
.mockReturnValueOnce('x')
.mockReturnValue(true);
console.log(myMock(), myMock(), myMock(), myMock());
//10 x true
1、用 mockRetrunValueOnce(value) 來預先設置函數(shù)的返回值
2、mymock() 返回預先設置的值
異步請求的數(shù)據(jù)模擬
let fetch = {
get:() =>{}
}
jest.mock(fetch)
fetch.get.mockResolvedValue({data:{},status:0})
fetch.get(url,options)
// {data:{},status:0}
4、常用全局方法
describe(message,()=>{}) : 創(chuàng)建塊
it(message,()=>{}) : 測試單元
5、ecpect 常用方法
expect(value) : 注入測試單元
expect.extend({}) : 拓展 expect 方法
expect.extend({
toBeBetween(received, arg1, arg2) {
const min = arg1;
const max = arg2;
if (received > min && received < max) {
return {
message: '',
pass: true,
};
}
return {
message: `received is between in ${min} - ${max}`,
pass: true,
};
},
});
expect(99).toBeBetween(1,100)
expect.anything() : 返回除了 null 和 undefined 意外的任何類型數(shù)據(jù)
expect.any(Number/String) : 任意 數(shù)字/字符串
expect.assertions(num) : 確定在塊中調(diào)用幾次異步
toBe(value) : 等于
toHaveBeenCalled() : 確定函數(shù)調(diào)用
toHaveBeenCalledTime(number) : 確定被調(diào)用的次數(shù)
toHaveBeenCalledWith(arg1,arg2) :取保調(diào)用的函數(shù)的值
toHaveBeenNthCalledWith(num,arg2) : 確保第幾個參數(shù)
toHaveRetruned() :確保有返回值
toHave[:Nth]RetrunedWith([:num,]arg) : 確保某一個有返回值
toContain(item) : 數(shù)組中是否包含
toMatch(regex) :正則表達式
enzyme
enzyme 一共有四個大的 api ( shallow 、mount 、render 、selectors )。
通過這四個 api 可以對 react 組件進行操作。
我們可以通過類似于 jquery 的操作來進行 test 。
總結
以上是生活随笔為你收集整理的react 单元测试 (jest+enzyme)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 如何改善GPS的漂移?
- 下一篇: 【微信小程序&腾讯地图】获取用户