Jest+enzyme測試React-native項(xiàng)目

一、搭建和配置

npm install jest --save-dev
npm install enzyme --save-dev
npm install enzyme-adapter-react-16 --save-dev
// es6 es7 tytpescript 語法轉(zhuǎn)換 
npm install babel-jest ts-jest --save-dev 
 // 為快照提供了json的組件格式
npm install enzyme-to-json --save-dev 
 //  mock canvas
npm install jest-canvas-mock --save --dev
1.環(huán)境配置

// 在根目錄創(chuàng)建jest.config.js并添加配置項(xiàng)module.exports = { 配置項(xiàng) }

module.exports = {
    preset: "react-native",
    ...
}

moduleFileExtensions 設(shè)置Jest要執(zhí)行測試文件的類型

moduleFileExtensions: ['ts','tsx','js','jsx']

transform設(shè)置一個(gè)入口,來告訴 Jest 要測試的資源 文件

  // 如果項(xiàng)目中采用typescript為技術(shù)棧,需要設(shè)置ts-jest轉(zhuǎn)譯代碼
  "^.+\\.(ts|tsx)$": "ts-jest",   
  // 設(shè)置babel-jest轉(zhuǎn)譯es6 es7代碼
  "^.+\\.(js|jsx)$": "babel-jest",
  // Jest環(huán)境不能處理css和圖片文件,需要通過工具來mock
  "^.+.(css|styl|less|sass|scss|png|jpg|ttf|woff|woff2)$": "jest-transform-stub",

項(xiàng)目使用webpack配置的alias如何兼容? 配置如下:

// Resolve alias in Jest not working
moduleNameMapper
     "^Controller/(.*)$": "<rootDir>/src/controller/$1",
        "^Service/(.*)$": "<rootDir>/src/service/$1",
           "^Store/(.*)$": "<rootDir>/src/store/$1",
          "^Styles/(.*)$": "<rootDir>/src/styles/$1",
          "^Router/(.*)$": "<rootDir>/src/router/$1",
          "^Common/(.*)$": "<rootDir>/src/common/$1"
};

transformIgnorePatterns 配置不忽略這些es庫, 從而使babel-jest/jest-ts去處理它們

    transformIgnorePatterns: [
        "node_modules/(?!(react-native|react-native-button|react-router-native/)"
    ]

展示單元測試覆蓋率

 collectCoverage: true

設(shè)置Jest配置文件

    setupFiles: [
        "<rootDir>/node_modules/jest-canvas-mock",
        "<rootDir>/jest.setup.js"
    ],

項(xiàng)目在中有使用到webpack.DefinePlugin插件在打包時(shí)根據(jù)運(yùn)行環(huán)境動(dòng)態(tài)注入的一些配置項(xiàng),在單元測試如何去配置呢?

  // A set of global variables that need to be available in all test environments
  globals: {       
      __PAF_STAGE__: 16,
      __ISUSEI18N__: true
      __DEV__: true,
     ...
 }

testRnviroment 測試環(huán)境,默認(rèn)值是:jsdom,可修改為node

  testEnvironment: 'jsdom'

rootDir 默認(rèn)值:當(dāng)前目錄,一般是package.json所在的目錄。

  rootDir: ' '

enzyme配置,在Jest.setup.js添加如下配置

  import Enzyme from 'enzyme';
  import Adapter from 'enzyme-adapter-react-16';
  Enzyme.configure({ adapter: new Adapter() });

備注: 項(xiàng)目中常用的Jest環(huán)境配置的主要注意的配置項(xiàng)都已經(jīng)說明清楚了,配置好這些你的項(xiàng)目環(huán)境配置基本可以運(yùn)行了,接下來就可以寫測試用例了,在寫測試用例前,有必要跟大家介紹下Jest和enzyme在使用的時(shí)候注意點(diǎn)~

2、Jest Matchers

   Matchers俗稱斷言庫,例如上面的expect().toBe()便是其中之一,其他常見用法如下:

1.相等斷言

toBe(value): 比較數(shù)字、字符串
toEqual(value): 比較對(duì)象、數(shù)組
toBeNull()
toBeUndefined()

2.包含斷言

toHaveProperty(keyPath, value): 是否有對(duì)應(yīng)的屬性
toContain(item): 是否包含對(duì)應(yīng)的值,括號(hào)里寫上數(shù)組、字符串
toMatch(regexpOrString): 括號(hào)里寫上正則

3.邏輯斷言

toBeTruthy()
toBeFalsy()
在JavaScript中,有六個(gè)falsy值:false,0,'',null, undefined,和NaN。其他一切都是Truthy。

toBeGreaterThan(number): 大于
toBeLessThan(number): 小于

4.not

取反,用法見下面例子

test('matchers',()=>{
    const a = {
        hello: 'jest',
        hi :{
            name: 'jest'
        }
    }
   const b = {
    hello: 'jest',
    hi:{
        name: 'jest'
    }
}
  // 以下結(jié)果均為true
  expect(a).toEqual(b)
  expect([1,2,3]).toEqual([1,2,3])
  expect(null).toBeNull()
  expect([1,2,3]).toContain(1)
  expect(b).toHaveProperty('hi')
  expect('123').toContain('2')
  expect('123').toMatch(/^\d+$/)
  expect('123').not.toContain('4')
})

使用npx jest測試執(zhí)行,結(jié)果為passed

3、enzyme支持三種方式的渲染:

  • 淺渲染shallow
    前面說過,Shallow Rendering用于將一個(gè)組件渲染成虛擬DOM對(duì)象,但是只渲染第一層,不渲染所有子組件,所以處理速度非??臁2⑶宜恍枰狣OM環(huán)境,因?yàn)楦緵]有加載進(jìn)DOM。

  • 完全渲染mount
    mount渲染用于將React組件加載為真實(shí)DOM節(jié)點(diǎn)。然而,真實(shí)DOM需要一個(gè)瀏覽器環(huán)境,為了解決這個(gè)問題,我們可以用到j(luò)sdom,也就是說我們可以用jsdom模擬一個(gè)瀏覽器環(huán)境去加載真實(shí)的DOM節(jié)點(diǎn)。 首先,使用下面的命令安裝jsdom模擬瀏覽器環(huán)境,安裝命令如下:

npm install --save-dev jsdom復(fù)制代碼
  • 靜態(tài)渲染render
    render靜態(tài)渲染,主要用于將React組件渲染成靜態(tài)的HTML字符串,然后使用Cheerio這個(gè)庫解析這段字符串,并返回一個(gè)Cheerio的實(shí)例對(duì)象,可以用來分析組件的html結(jié)構(gòu)。

shallow是最快的,這是因?yàn)閟hallow的局限性,只渲染第一層,不渲染所有子組件。事實(shí)證明,render的效率是mount的兩倍。 那么問題來了,mount存在的價(jià)值是什么?當(dāng)然是有價(jià)值的,shallow和mount因?yàn)槎际莇om對(duì)象的緣故,所以都是可以模擬交互的。

常用函數(shù)

enzyme中有幾個(gè)比較核心的函數(shù)需要注意,如下:

  • simulate(event, mock):用來模擬事件觸發(fā),event為事件名稱,mock為一個(gè)event object;
  • instance():返回測試組件的實(shí)例;
  • find(selector):根據(jù)選擇器查找節(jié)點(diǎn),selector可以是CSS中的選擇器,也可以是組件的構(gòu)造函數(shù),以及組件的display name等;
  • at(index):返回一個(gè)渲染過的對(duì)象;
  • get(index):返回一個(gè)react node,要測試它,需要重新渲染;
  • contains(nodeOrNodes):當(dāng)前對(duì)象是否包含參數(shù)重點(diǎn) node,參數(shù)類型為react對(duì)象或?qū)ο髷?shù)組;
  • text():返回當(dāng)前組件的文本內(nèi)容;
  • html(): 返回當(dāng)前組件的HTML代碼形式;
  • props():返回根組件的所有屬性;
  • prop(key):返回根組件的指定屬性;
  • state():返回根組件的狀態(tài);
  • setState(nextState):設(shè)置根組件的狀態(tài);
  • setProps(nextProps):設(shè)置根組件的屬性;

開發(fā)過程中遇到的問題:

1、TypeError: environment.setup is not a function

FAIL __test__/app.test.tsx
  ● Test suite failed to run

    TypeError: environment.setup is not a function

      at node_modules/jest-runner/build/run_test.js:112:23

解決方案:
報(bào)這種錯(cuò)誤可能有些許多原因,我的項(xiàng)目是由于我們對(duì)React-native 0.52版本 做了深度改造,造成最新的Jest 24版本不兼容,降級(jí)的Jest23版本正常運(yùn)行

參考方案:
https://stackoverflow.com/questions/48149004/typeerror-environment-setup-is-not-a-function-in-react-testing

https://stackoverflow.com/questions/48042896/why-will-jest-not-run-typeerror-environment-setup-is-not-a-function

總結(jié):

參考文檔
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容