使用Enzyme和Jest 測試React組件(上)

1 Enzyme 是什麼?

Enzyme 是一類大分子生物催化劑。酶能加快化學反應的速度(即具備催化做用)
— wikipediajavascript

Airbnb開源的 React 測試類庫 Enzyme 提供了一套簡潔強大的 API,並經過 jQuery 風格的方式進行DOM 處理,開發體驗十分友好。不只在開源社區有超高人氣,同時也得到了React 官方的推薦。
Airbnb.iocss

Jest 咱們上一篇已經說過了,今天主角是Enzyme , 如字面意思,Enzyme 是酶、有催化做用。那麼在React 組件測試中和Jest 產生了什麼化學🎿反應呢?html


2 課前準備

2.1 項目

這裏咱們使用 create-react-app 初始化一個項目前端

npm i -g create-react-app
npx create-react-app enzyme-in-action --use-npm
cd enzyme-in-action
npm start 
複製代碼

會自動打開瀏覽器將看到這個頁面。 java

這個是 create-react-app 起手式,若是不太瞭解建議 Create a New React App – React 瞭解下。

2.2 準備jest 和 enzyme配置

在::package.json:: 中修改 scriptsreact

- "test": "react-scripts test",
+ "test": "jest",
複製代碼

在::package.json:: 中增長jest配置git

"jest": {
  "transform": {
    "^.+\\.jsx?$": "babel-jest",
    "^.+\\.svg$": "jest-svg-transformer"
  },
  "moduleNameMapper": {
    "\\.(css|less)$": "identity-obj-proxy"
  }
}
複製代碼

安裝依賴包npm

npm i -D jest babel-jest babel-core babel-preset-env babel-preset-react enzyme enzyme-adapter-react-16 jest-svg-transformer identity-obj-proxy
複製代碼

jest-svg-transformeridentity-obj-proxy 是爲了保證 jsx 文件中的
import logo from './logo.svg' import './App.css' 被正常渲染出來json

2.3 背景知識

  1. Enzyme 它提供三種測試方法:
    • ::shallow::
    • ::render::
    • ::mount::
  2. wrapper wrapper是enzyme包裝好的類,以供api使用
  3. shallow 在單元測試的過程當中,淺渲染將一個組件渲染成虛擬DOM對象,並不會渲染其內部的子組件,也不是真正完整的React Render,沒法與子組件互動。

3 起手式

修改create-react-app 爲咱們生成好的::src/App.test.js::api

import React from 'react'
import App from './App'
import { configure, shallow } from 'enzyme'
import Adapter from 'enzyme-adapter-react-16'

configure({ adapter: new Adapter() })

describe(`<App />`, () => {
  it('should render App', () => {
    const warpper = shallow(<App />) console.log(warpper.debug()) }) }) 複製代碼

npm run test

warpper.debug() 已經輸出渲染的Dom,這個 warpper用來咱們後面,用jQuery語法來測試。


4 find測試節點

在::app.js::中增長

<img src={logo} className="App-logo" alt="logo" />
+ <h1>Welcome to React</h1>
  <p>
複製代碼

如今咱們來正式寫單測 ::app.test.js::

describe(`測試<App />`, () => {
  const warpper = shallow(<App />) it('1. 包含一個p標籤', () => { expect(warpper.find('p').length).toBe(1) }) it('2. class爲"App-link"的元素能正常被渲染', () => { expect(warpper.find('.App-link').exists()).toBeTruthy() }) it('3. header的class爲「App-header」', () => { expect(warpper.find('header').hasClass('App-header')).toBeTruthy() }) it('4. header有3個子元素', () => { expect(warpper.find('header').children().length).toBe(4) }) it('5. 測試H1標籤的內容', () => { expect(warpper.find('h1').text()).toBe('Welcome to React') }) it('6. 測試image標籤class', () => { expect(warpper.find({ alt: 'logo' }).hasClass('App-logo')).toBeTruthy() }) }) 複製代碼

寫過jQuery 的同窗有沒有很熟悉?這裏不過多解釋。

這裏推薦一個VsCode插件 Jest 在每一個單元測試前面會有一個icon標示當前是否過測。


5 使用snapshots 測試組件

按照find的方法測試組件,須要寫多少單元測試,jest 爲咱們提供了一種快照的方式,來對比組件的變化。 安裝依賴:

npm i -D enzyme-to-json
複製代碼

在::app.test.js::中增長測試

import Adapter from 'enzyme-adapter-react-16'
+ import toJson from 'enzyme-to-json'
複製代碼
describe(`測試<App /> snapshots`, () => {
  const tree = shallow(<App />) it('1. 匹配快照', () => { expect(toJson(tree)).toMatchSnapshot() }) }) 複製代碼

npm run test 在命令行中會有

› 1 snapshot written.
Snapshot Summary
 › 1 snapshot written from 1 test suite.
複製代碼

這時候咱們看工程目錄
增長了 src/__snapshots__/App.test.js.snap這個就是jest的快照。jest原生的快照比較複雜, enzyme-to-json爲咱們作了簡化。

第一次寫toMatchSnapshot 的時候,被建立。當咱們修改測試的時候它被更新。
咱們來嘗試修改一下react 組件 看會有什麼事情發生

修改::app.js::

- <h1>Welcome to React</h1>
+ <h1>Welcome to React Jest Enzyme</h1>
複製代碼

npm run test 在命令行中會有 錯誤信息,告訴你哪裏發生了變化

tips: 更新快照的命令:jest --updateSnapshot 在watch 的狀況下 按u 更新快照,若是你用的是vscode 那麼修改組件的時候會提醒你是否更新。

6 測試含有「props」的組件

首先增長一個<Link>組件 ::App.js::

export class Link extends PureComponent {
  render() {
    const { hide, address } = this.props
    return hide ? null : <a href={address}>Click</a>
  }
}
複製代碼

在::app.test.js::中增長測試

describe(`測試<Link />`, () => {
  it('1. 測試link組件', () => {
    const warpper = shallow(<Link address="https://www.google.com" />) expect(warpper.props().href).toBe('https://www.google.com') }) it('2. 測試設置Link props', () => { const warpper = shallow(<Link />) expect(warpper.find('a').length).toBe(1) warpper.setProps({ hide: true }) expect(warpper.find('a').length).toBe(0) }) }) 複製代碼
  1. warpper.props()的結果爲
{ href: 'https://www.google.com', children: 'Click' }
複製代碼
  1. 在case :2. 測試設置Link props 中用warpper.setProps() 動態的給<Link />設置參數驗證組件是否被正常渲染

X 未完待續…

後面還有 :如何測試state ,生命週期,等等。 Jest 沒寫盡興,再整理一篇進階的文章,有小夥伴不清楚什麼是集成測試和單元測試,後面整理一篇cypress相關的文章。 秋日的北京週末,開始起霧霾,週末陪周老師備考高級教師資格證,才能坐電腦前寫這麼長時間。

2010年末來北京,一晃8年過去了。剛來北京的時候無知但無畏,到如今無味且無爲。記念一下這個心情複雜的時刻。望之後不管在什麼地方,坦然以對。
— 今天的豆瓣日記
來自豆友分享的專輯💽 空中 ベスト・オブ (豆瓣) 灰常好聽,雖然夜已深,仍是元氣滿滿,開始寫第三篇。

技術能力有限,有什麼不妥之處請指正。 有什麼關於前端方面有疑惑🤔的方面,能夠留言交流,會放到後面的寫做計劃中。

相關文章
相關標籤/搜索