使用 Enzyme 測試 react-redux-app(接上一篇)
使用 enzyme+jest 可以很方便的來測試我們的 react 應用
測試需要關注哪些方面
- 頁面的結構的測試(一般是去 判斷 dom 結構對不對)
- 樣式的測試(這個比較複雜,可能需要我們去截圖對比,簡單點的做法,就直接對比樣式代碼是否有變更,這個只對 inline-style 有效)
- 交互的測試( 測試一些交互能否正常被觸發)
安裝依賴
yarn add -D enzyme enzyme-adapter-react-16 @types/enzyme @types/enzyme-adapter-react-16
設置啓動文件
按照 enzyme 文檔,測試前是需要做一些準備工作的, 所以我們在根目錄下添加test.setup.ts
// test.setup.ts
import { configure } from 'enzyme'
import * as Adapter from 'enzyme-adapter-react-16'
configure({ adapter: new Adapter() })
同時修改jest.config.js
文件
module.exports = {
preset: 'ts-jest',
testEnvironment: 'node',
setupTestFrameworkScriptFile: '<rootDir>/test.setup.ts'
}
模擬瀏覽器環境
react 應用運行的時候是在瀏覽器環境,但是我們測試的時候是在 node 環境,所以需要我們模擬出瀏覽器環境才能正確的運行測試。之前的做法是在無頭瀏覽器中跑測試代碼,但現在我們有一個更好的、更輕量的方法,就是使用jsdom
。
安裝 jsdom
yarn add -D jsdom @types/jsdom
# 順帶安裝一下requestAnimation的模擬,react需要
yarn add -D raf
修改test.setup.ts
import 'raf/polyfill'
import { configure } from 'enzyme'
import * as Adapter from 'enzyme-adapter-react-16'
import * as jsdom from 'jsdom'
const { window } = new jsdom.JSDOM('<!doctype html><html><body></body></html>')
global.window = window
global.document = window.document
configure({ adapter: new Adapter() })
編寫測試
測試簡單的組件
我們先寫一個測試文件測一個簡單的組件test/BtnBack.test.ts
/**
* 返回按鈕
*/
import * as React from 'react'
import { Button } from 'antd'
import { ButtonProps } from 'antd/lib/button'
import { win } from '../../util'
const BtnBack: React.SFC<ButtonProps> = props => (
<Button onClick={win.goBack} {...props}>
返回
</Button>
)
export default BtnBack
import * as React from 'react'
import { shallow } from 'enzyme'
import BtnBack from '../../src/components/BtnBack'
import { Button } from 'antd'
test('<BtnBack />', () => {
const wrapper = shallow(<BtnBack />)
// 這部分是 結構測試
const props = wrapper.find(Button).props()
expect(props.children).toEqual('返回')
// 這部分是 交互測試
global.window = {
history: {
back: jest.fn()
}
}
wrapper.find(Button).simulate('click')
expect(global.window.history.back).toBeCalled()
})
done! 是不是很簡單。
測試 connected 組件
測試 connected 組件有兩種方法。
- 一種是使用dive方法,dive 能剝離 第一層組件,返回 connected 組件裏第一個非 dom 的 child-node,也就是我們自己寫的組件,然後就像測一個簡單組件一樣去測 這個組件。當然,測試的時候需要模擬出 connected 產生的一些 props。
- 另一種就是模擬出 redux-store,我用的是這種
安裝 mock-store
yarn add -D redux-mock-store @types/redux-mock-store
編寫測試
import * as React from 'react'
import Selector from '../../src/components/Selector'
import configureStore from 'redux-mock-store'
import { mount } from 'enzyme'
import { Select } from 'antd'
const middlewares = []
const mockStore = configureStore(middlewares)
const initState = {
dataList: [
{
value: 1,
desc: '1'
},
{
value: 2,
desc: '2'
}
]
}
const store = mockStore(initState)
test('loadActin: Function, dataSouce: any', () => {
let count = 0
const loadAction = () => {
count++
return {
type: 'TEST'
}
}
const wrapper = mount(
<Selector
loadAction={loadAction}
statePicker={state => state.dataList}
store={store}
>
{(dataSource, Option) => {
return dataSource.map((e: any, i: number) => (
<Option key={i} value={e.value}>
{e.desc}
</Option>
))
}}
</Selector>
)
// action 被調用
expect(count).toBe(1)
// 渲染出正確的option 數量
const opts = wrapper.find(Select).prop('children') as any[]
expect(opts.length).toBe(2)
}
done! 是不是也很簡單。
其他例子
大部分測試情況,都能在 enzyme 的文檔中找到例子,我這邊只是簡單的介紹一下,enzyme 如何使用。
測試覆蓋率
測試覆蓋率是評價測試一個很重要的指標,我們可以通過yarn jest --coverage
生成測試報告,查看代碼中沒有被測試到的分支,一點點的提高測試覆蓋率
最後
可能大部分項目礙於各種情況,時間不夠,需求變化太快等等,放棄編寫測試,全部交給測試人員去測。但是,寫不寫測試是一回事,會不會寫測試是另一會事。
希望各位在這又收穫了一點小知識。:)