使用 Enzyme 測試 react-redux-app(接上一篇)

使用 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生成測試報告,查看代碼中沒有被測試到的分支,一點點的提高測試覆蓋率

最後

可能大部分項目礙於各種情況,時間不夠,需求變化太快等等,放棄編寫測試,全部交給測試人員去測。但是,寫不寫測試是一回事,會不會寫測試是另一會事。
希望各位在這又收穫了一點小知識。:)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章