1 Enzyme 是什麼?
Enzyme
是一類大分子生物催化劑。酶能加快化學反應的速度(即具有催化作用)
— wikipedia
Airbnb開源的 React 測試類庫 Enzyme 提供了一套簡潔強大的 API,並通過 jQuery 風格的方式進行DOM 處理,開發體驗十分友好。不僅在開源社群有超高人氣,同時也獲得了React 官方的推薦。
— Airbnb.io
Jest 我們上一篇已經說過了,今天主角是Enzyme , 如字面意思,Enzyme 是酶、有催化作用。那麼在React 元件測試中和Jest 產生了什麼化學?反應呢?
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
複製程式碼
會自動開啟瀏覽器將看到這個頁面。
這個是create-react-app
起手式,如果不太瞭解建議Create a New React App – React 瞭解下。
2.2 準備jest 和 enzyme配置
在::package.json:: 中修改 scripts
- "test": "react-scripts test",
+ "test": "jest",
複製程式碼
在::package.json:: 中增加jest
配置
"jest": {
"transform": {
"^.+\\.jsx?$": "babel-jest",
"^.+\\.svg$": "jest-svg-transformer"
},
"moduleNameMapper": {
"\\.(css|less)$": "identity-obj-proxy"
}
}
複製程式碼
安裝依賴包
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-transformer
和identity-obj-proxy
是為了保證 jsx 檔案中的
import logo from './logo.svg'
import './App.css'
被正常渲染出來
2.3 背景知識
Enzyme
它提供三種測試方法:- ::shallow::
- ::render::
- ::mount::
wrapper
wrapper是enzyme包裝好的類,以供api使用shallow
在單元測試的過程中,淺渲染將一個元件渲染成虛擬DOM物件,並不會渲染其內部的子元件,也不是真正完整的React Render,無法與子元件互動。
3 起手式
修改create-react-app
為我們生成好的::src/App.test.js::
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)
})
})
複製程式碼
warpper.props()
的結果為
{ href: 'https://www.google.com', children: 'Click' }
複製程式碼
- 在case :
2. 測試設定Link props
中用warpper.setProps()
動態的給<Link />
設定引數驗證元件是否被正常渲染
X 未完待續…
後面還有 :如何測試state ,生命週期,等等。 Jest 沒寫盡興,再整理一篇進階的文章,有小夥伴不清楚什麼是整合測試和單元測試,後面整理一篇cypress相關的文章。 秋日的北京週末,開始起霧霾,週末陪周老師備考高階教師資格證,才能坐電腦前寫這麼長時間。
2010年底來北京,一晃8年過去了。剛來北京的時候無知但無畏,到現在無味且無為。紀念一下這個心情複雜的時刻。望以後無論在什麼地方,坦然以對。
— 今天的豆瓣日記
來自豆友分享的專輯? 空中 ベスト・オブ (豆瓣) 灰常好聽,雖然夜已深,還是元氣滿滿,開始寫第三篇。
技術能力有限,有什麼不妥之處請指正。 有什麼關於前端方面有疑惑?的方面,可以留言交流,會放到後面的寫作計劃中。