【前端單元測試入門02】react的單元測試之Enzyme

来源:https://www.cnblogs.com/vvjiang/archive/2018/03/19/8599980.html
-Advertisement-
Play Games

React項目的單元測試 React的組件結構和JSX語法,對 "上一章" 的內容來講進行測試顯得很勉強。 React官方已經提供了一個測試工具庫: "react dom/test utils" 只是用起來不夠方便,於是有了一些第三方的封裝庫,比如Airbnb公司的 "Enzyme" 測試項目的配置 ...


React項目的單元測試

React的組件結構和JSX語法,對上一章的內容來講進行測試顯得很勉強。
React官方已經提供了一個測試工具庫:react-dom/test-utils
只是用起來不夠方便,於是有了一些第三方的封裝庫,比如Airbnb公司的Enzyme

測試項目的配置

本次測試項目是根據上一章的測試項目衍生而來,包含上一章講到的Mocha和chai,這裡只介紹新加的一些模塊。
項目結構圖如下:
測試項目結構圖

因為是React項目,所以自然需要安裝React的一些東西:

npm install --save react react-dom babel-preset-react

然後.babelrc文件內容改為

{
  "presets": [ "es2015","react" ]
}

example.jsx的內容為:

import React from 'react'

const Example=(props)=>{
    return (<div>
            <button>{props.text}</button>
        </div>)
}
export default Example

example.test.js的內容暫時為空

Enzyme 的安裝與配置

npm install --save-dev enzyme

而enzyme還需要根據React的版本安裝適配器,適配器對應表如下:

Enzyme Adapter Package React semver compatibility
enzyme-adapter-react-16 ^16.0.0
enzyme-adapter-react-15 ^15.5.0
enzyme-adapter-react-15.4 15.0.0-0 - 15.4.x
enzyme-adapter-react-14 ^0.14.0
enzyme-adapter-react-13 ^0.13.0

那麼因為我們安裝的React版本為^16.2.0
所以需要安裝:

npm install --save-dev enzyme-adapter-react-16

Enzyme 的使用

現在開始用Enzyme為example.jsx編寫測試代碼:

import {assert} from 'chai'
import React from 'react'
import Enzyme from 'enzyme'
import Adapter from 'enzyme-adapter-react-16'
import Example from '../src/example'

const {shallow}=Enzyme

Enzyme.configure({ adapter: new Adapter() })

describe('Enzyme的淺渲染測試套件', function () {
  it('Example組件中按鈕的名字為text的值', function () {
    const name='按鈕名'
    let app = shallow(<Example text={name} />)
    assert.equal(app.find('button').text(),name)
  })
})

如上面代碼所示,在使用Enzyme 前需要先適配React對應的版本

Enzyme.configure({ adapter: new Adapter() })

而為了避免每個測試文件都這麼寫,可以再test目錄下新建一個配置文件:

import Enzyme from 'enzyme';
import Adapter from 'enzyme-adapter-react-16';

Enzyme.configure({
  adapter: new Adapter(),
});

export default Enzyme;

然後測試文件的時候只需要引用這個配置文件即可:

import {assert} from 'chai'
import React from 'react'
import Enzyme from './config/Enzyme.config';
import Example from '../src/example'

const {shallow}=Enzyme

describe('Enzyme的淺渲染測試套件', function () {
  it('Example組件中按鈕的名字為text的值', function () {
    const name='按鈕名'
    let app = shallow(<Example text={name} />)
    assert.equal(app.find('button').text(),name)
  })
})

Enzyme 的使用之淺渲染shallow

上面的例子中就用到淺渲染shallow 。
Shallow Rendering(淺渲染)指的是,將一個組件渲染成虛擬DOM對象,但是只渲染第一層,不渲染所有子組件,所以處理速度非常快。它不需要DOM環境,因為根本沒有載入進DOM。
shallow的函數輸入組件,返回組件的淺渲染結果,而返回的結果可以用類似jquery的形式獲取組件的信息。
運行

npm test 

也就是:

mocha --require babel-core/register

得到以下結果:
淺渲染測試運行結果

淺渲染測試與子組件的相關的代碼:

現在修改我們的例子,新加一個sub.jsx:

import React from 'react'

const Sub=(props)=>{
    return (<span>{props.text}</span>)
}
export default Sub

在原來的example.jsx中使用Sub,形成嵌套:

import React from 'react'
import Sub from './sub'

const Example=(props)=>{
    return (<div>
            <button>{props.text}</button>
            <Sub text={props.text}  />
        </div>)
}
export default Example

使用shadow測試子組件的代碼:

import {assert} from 'chai'
import React from 'react'
import Enzyme from 'enzyme'
import Adapter from 'enzyme-adapter-react-16'
import Example from '../src/example'

const {shallow,mount}=Enzyme

Enzyme.configure({ adapter: new Adapter() })

describe('Enzyme shallow的淺渲染(Shallow Rendering)中', function () {
  it('Example組件中按鈕的名字為子組件Sub中span的值', function () {
    const name='按鈕名'
    let app = shallow(<Example text={name} />)
    const buttonObj=app.find('button')
    const spanObj=app.find('span')

    console.info(`查找到button的個數:${buttonObj.length}`)
    console.info(`查找到span的個數:${spanObj.length}`)

    assert.equal(buttonObj.text(),spanObj.text())
  })
})

測試結果為:
淺渲染測試子組件的結果

如上圖所示,shallow所得到的淺渲染對象中差找不到子組件Sub的span元素。
為瞭解決上面這種情況,Enzyme給出的解決方案為用mount實現 Full DOM Rendering

Enzyme 的使用之mount

mount方法用於將React組件載入為真實DOM節點。
然而真實DOM需要一個瀏覽器環境,為瞭解決這個問題,我們可以用到jsdom.
下麵是jsdom的官方介紹:

jsdom is a pure-JavaScript implementation of many web standards, notably the WHATWG DOM and HTML Standards, for use with Node.js. In general, the goal of the project is to emulate enough of a subset of a web browser to be useful for testing and scraping real-world web applications.

也就是說我們可以用jsdom模擬一個瀏覽器環境去載入真實的DOM節點。
首先安裝jsdom:

npm install --save-dev jsdom

然後在test目錄下新建一個文件setup.js:

import jsdom from 'jsdom';
const { JSDOM } = jsdom;

if (typeof document === 'undefined') {
    const dom=new JSDOM('<!doctype html><html><head></head><body></body></html>');
    global.window =dom.window;
    global.document = global.window.document;
    global.navigator = global.window.navigator;
}

最後修改我們的package.json中的測試腳本為:

 "scripts": {
    "test": "mocha --require babel-core/register --require ./test/setup.js"
  }

這樣在運行npm test時,會先用babel解析js,然後再執行setup.js中的代碼,給global對象模擬一個瀏覽器環境。

在配置好模擬瀏覽器環境後,修改測試代碼為:

import {assert} from 'chai'
import React from 'react'
import Enzyme from 'enzyme'
import Adapter from 'enzyme-adapter-react-16'
import Example from '../src/example'

const {shallow,mount}=Enzyme

Enzyme.configure({ adapter: new Adapter() })

describe('Enzyme mount的DOM渲染(Full DOM Rendering)中', function () {
  it('Example組件中按鈕的名字為子組件Sub中span的值', function () {
    const name='按鈕名'
    let app = mount(<Example text={name} />)

    const buttonObj=app.find('button')
    const spanObj=app.find('span')

    console.info(`查找到button的個數:${buttonObj.length}`)
    console.info(`查找到span的個數:${spanObj.length}`)

    assert.equal(buttonObj.text(),spanObj.text())
  })
})

運行

npm test

結果為:
mount的Full DOM Rendering測試結果

如上,在mount得到的結果中可以找到子組件的元素

Enzyme 的使用之render

而Enzyme還提供了一個不需要jsdom模擬環境解決子組件測試的方法:render
Enzyme的render函數得到的結果被稱為Static Rendered Markup,以下為官方的介紹

enzyme's render function is used to render react components to static HTML and analyze the resulting HTML structure.
render returns a wrapper very similar to the other renderers in enzyme, mount and shallow; however, render uses a third party HTML parsing and traversal library Cheerio. We believe that Cheerio handles parsing and traversing HTML extremely well, and duplicating this functionality ourselves would be a disservice.

意思就是說render會根據react組件得到一個靜態HTML文本結果,藉助一個第三方的HTML解析庫Cheerio去生成一個類似於mount和shallow得到的封裝對象。

修改測試代碼為:

import {assert} from 'chai'
import React from 'react'
import Enzyme from 'enzyme'
import Adapter from 'enzyme-adapter-react-16'
import Example from '../src/example'

const {shallow,mount,render}=Enzyme

Enzyme.configure({ adapter: new Adapter() })

describe('Enzyme render的靜態HTML渲染(Static Rendered Markup)中', function () {
  it('Example組件中按鈕的名字為子組件Sub中span的值', function () {
    const name='按鈕名'
    let app = render(<Example text={name} />)

    const buttonObj=app.find('button')
    const spanObj=app.find('span')

    console.info(`查找到button的個數:${buttonObj.length}`)
    console.info(`查找到span的個數:${spanObj.length}`)

    assert.equal(buttonObj.text(),spanObj.text())
  })
})

測試結果為:
render測試結果

小結

簡而言之,Enzyme主要包括三個測試:
一個是淺渲染的shallow,這個生成虛DOM對象,所以渲染最快,然而它並不能測試子組件的相關代碼。
另一個是DOM渲染mount,它會生成完整的DOM節點,所以可以測試子組件。但是要依賴一個用jsdom模擬的瀏覽器環境。
最後一個是HTML文本渲染render,它會將react組件渲染為html文本,然後在內部通過Cheerio自動生成一個Cheerio對象。
文中介紹了簡單的用法,具體的API文檔見:
Shallow Rendering
Full DOM Rendering
Static Rendered Markup


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...