React搭建jest+enzyme單元測試框架

2021-04-19 15:00:21

其實參考官方檔案很容易就完成搭建了,因此本文也是對官網進行一個測試搭建過程的簡單演練。
https://jestjs.io/
https://enzymejs.github.io/en...

安裝依賴包

  • jest -- 測試框架
  • enzyme -- React的測試工具,可以使用mount、render、shallow渲染react元件,測試元件的輸出、state、props等
  • babel-jest -- jest新增babel-jest後,會自動使用babel編譯程式碼
  • @babel/core -- babel編譯核心模組
  • @babel/preset-env -- 環境預設,將最新的js語言轉化為es5
  • @babel/preset-react -- babel對react轉換
  • @babel/preset-typescript -- babel對ts語言轉換
  • enzyme-adapter-react-16 -- 用於連線react和jest的介面卡,需要根據react版本下載,部分版本對照參考表格1-1
  • identity-obj-proxy -- 用於css、js檔案的mock,否則會包解析不了css檔案的錯誤
  • jsdom -- 模擬Web瀏覽器的子集用於測試(因為enzyme的render在構建時需要依賴window、document等bom物件)

當然為了方便開發,安裝對應的types很有必要

  • @types/jest
  • @types/enzyme

enzyme-adapter-react官網上目前的版本列表,其它版本請移步官網查詢
表格1-1

enzyme介面卡版本React版本
enzyme-adapter-react-16^16.4.0-0
enzyme-adapter-react-16.3~16.3.0-0
enzyme-adapter-react-16.2~16.2
enzyme-adapter-react-16.1~16.0.0-0~16.1
enzyme-adapter-react-15^15.5.0
enzyme-adapter-react-15.415.0.0-0 - 15.4.x
enzyme-adapter-react-14^0.14.0
enzyme-adapter-react-13^0.13.0

babel組態檔

.babelrc

{
  "presets": [
    [
      "@babel/preset-env",
      {
        "targets": {
          "node": "current"
        }
      }
    ],
    "@babel/preset-typescript",
    "@babel/preset-react"
  ]
}

jest組態檔

jest.config.js

module.exports = {
  testEnvironment: 'node',
  roots: ['<rootDir>'],
  // 測試檔案是src目錄下*.test.jsx或者*.test.tsx的檔案
  testRegex: 'src/(.+)\\.test\\.(jsx?|tsx?)$', 
  // 自定義轉換方式,轉換jsx、tsx檔案
  transform: {
    '^.+\\.(j|t)sx?$': '<rootDir>/node_modules/babel-jest',
  },
  // 模組資源對映,例如alias的設定
  moduleNameMapper: {
    // 用於css、js、圖片等檔案的mock
    '\\.(css|less|scss)$': 'identity-obj-proxy',
    '\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$': 'identity-obj-proxy',
    // alias
    '^@mock/(.*)$': '<rootDir>/mock/$1',
  },
  testPathIgnorePatterns: ['\\node_modules\\'],
  moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'json', 'node'],
  // 覆蓋率從哪些檔案收集,設定後即使0覆蓋率的檔案也會計算進來
  collectCoverageFrom: ['src/**/*.{ts,tsx,js,jsx}', '!**/node_modules/**', '!**/dist/**'],
  // 測試報告輸出地址
  coverageDirectory: '<rootDir>/coverage',
  // 在每個測試檔案執行之前,執行一些程式碼以設定或設定測試框架。
  setupFilesAfterEnv: ['./src/test/setupTests.js'],
};

jest初始化檔案

setupTests.js

import { configure } from 'enzyme';
import Adapter from 'enzyme-adapter-react-16';
import jsdom from 'jsdom';

// 設定react和enzyme的介面卡
configure({ adapter: new Adapter() });

// 設定給render掛載在global用到的dom物件
const { JSDOM } = jsdom;
const { window } = new JSDOM('');
const { document } = new JSDOM(``).window;
global.document = document;
global.window = window;

命令設定

package.json

"scripts": {
  ...
  "test": "jest"
  "test:coverage": "jest --coverage"
}

npm run test即可執行所有的單元測試
npm run test:coverage就可以執行生成覆蓋率報告的單元測試

單元測試程式碼編寫範例

測試一個checkbox元件

import { mount, ReactWrapper } from 'enzyme';
import CheckBox, { Props } from './index';
import React from 'react';

describe('CheckBox', () => {
...
it('should emit onChange corretly', () => {
    const props: Props = {
      checked: false,
      option: { label: 'test1', value: '111' },
      onChange: jest.fn(),
    };
    const wrapper = mount(<CheckBox {...props}></CheckBox>);
    wrapper.find('.checkbox-item').simulate('click');
    expect(onChange).toHaveBeenCalledWith({ checked: true, option });
  });
});

單個測試偵錯方法

在開發過程中,我們可能只想執行一個測試case,有2個方案可以解決

  1. 修改jest.config.js(不要提交到線上)

    module.exports = {
      ...
      // 修改為指定檔案
      testRegex: 'src/(.+)\\checkbox\\.test\\.(jsx?|tsx?)$', 
  2. vscode編輯器安裝外掛Jest Runner
    如圖,安裝後每個case都可以單獨執行或者偵錯。
    image.png