做爲一個前端工程師,我是很想去謝單元測試的,由於天天的需求不少,還要去編寫測試代碼,感受時間都不夠用了。javascript
不過最近開發了一個比較複雜的項目,讓我感受一旦項目大了、複雜了,並且仍是多人維護一個應用,編寫測試代碼,css
仍是頗有必要的。畢竟這樣作完以後,後邊的維護會輕鬆不少。前端
測試代碼的最小單元,一個函數就是一個單元java
主要用到的測試工具是 jest 和 enzymenode
jest 是 facebook 發佈的一個開源的,基於 jasmine 框架的 javascript 單元測試工具它提供了不少有效的功能,react
包含了內置的測試環境的 DOM API 來操做 Dom、斷言庫、mock 等功能,而且 jest 是 react 的官網上面推薦jquery
的工具。webpack
enzyme 是 Airbnb 開源的 react 測試類庫,提供了一套簡潔強大的 api ,能夠經過 jq 的風格進行 dom 處理,git
還能夠引用一些其餘的 dom 操做庫。github
react 項目是基於 webpack + babel 來進行構建的。
首先須要添加一些 jest + enzyme 的 npm 包
yarn add jest enzyme babel-jest regenerator-runtime react-test-renderer
enzyme 須要安裝對應的 react 的 adapter 版本
yarn add enzyme-adapter-react-16
一、package.json
"scripts": { "test": "jest --colors --coverage" },
添加顏色和現實覆蓋率
.babelrc 文件
"env": { // 單元測試下配置 "test": { "presets": [ "react", "react-optimize", [ "env", { "modules": "commonjs", // 主要是添加這個 "debug": true, "useBuiltIns": false, "targets": { "browsers": "defaults" } } ], "stage-0" ] } }
由於測試環境的在 babel 中的配置 dev 爲 test。
因此這裏須要特殊配置,modules 的形式是 commonjs
添加jest配置文件jest.config
module.exports = { roots: ['<rootDir>/__test__/', '<rootDir>/src/'], // 測試的目錄 modulePaths: ['<rootDir>'], coveragePathIgnorePatterns: ['/node_modules/', '/tests/setup.js'], //忽略統計覆蓋率的文件 // bail: true, // testRegex: '', // 後綴名稱 // testPathIgnorePatterns: 'est', // 忽略路徑 // moduleNameMapper: { // 與測試無關的資源文件贊成mock 掉,這樣在import 的時候就不會真的引入這些文件 // '^import?': '<rootDir>/build/jestImportMock.js', // '\\.(css|less|gif|jpg|jpeg|png)$': '<rootDir>/build/jestStyleMock.js', // }, };
一、簡單測試結構
function sum(a,b){ return a+b; } it('adds 1 + 2 to equal 3', () => { expect(sum(1, 2)).toBe(3); });
二、異步的測試結構
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); });
三、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 狀態
一、jest.fn 用來建立一個 mock function
二、mockCallback.mock 能夠訪問 mock function 的狀態
mock 的屬性:
calls : 調用的參數數組,保存了每次調用的入參
calls.length : 調用次數
calls[0][0] : 第一次調用的時候的第一個參數
results:調用的結果數組
results[0].value : 第一次調用的返回結果
執行 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
一、用 mockRetrunValueOnce(value) 來預先設置函數的返回值
二、mymock() 返回預先設置的值
異步請求的數據模擬
let fetch = { get:() =>{} } jest.mock(fetch) fetch.get.mockResolvedValue({data:{},status:0}) fetch.get(url,options) // {data:{},status:0}
describe(message,()=>{}) : 建立塊
it(message,()=>{}) : 測試單元
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 意外的任何類型數據
expect.any(Number/String) : 任意 數字/字符串
expect.assertions(num) : 肯定在塊中調用幾回異步
toBe(value) : 等於
toHaveBeenCalled() : 肯定函數調用
toHaveBeenCalledTime(number) : 肯定被調用的次數
toHaveBeenCalledWith(arg1,arg2) :取保調用的函數的值
toHaveBeenNthCalledWith(num,arg2) : 確保第幾個參數
toHaveRetruned() :確保有返回值
toHave[:Nth]RetrunedWith([:num,]arg) : 確保某一個有返回值
toContain(item) : 數組中是否包含
toMatch(regex) :正則表達式
enzyme 一共有四個大的 api ( shallow 、mount 、render 、selectors )。
經過這四個 api 能夠對 react 組件進行操做。
咱們能夠經過相似於 jquery 的操做來進行 test 。