简介
Enzyme是由Airbnb开源的一个React的JavaScript测试工具,使React组件的输出更加容易extrapolate 。Enzyme的API和jQuery操做DOM同样灵活易用,由于它使用的是cheerio库来解析虚拟DOM,而cheerio的目标则是作服务器端的jQuery。Enzyme兼容大多数断言库和测试框架,如chai、mocha、jasmine等。html
安装与配置
使用enzyme以前,须要在项目中安装enzyme依赖,安装的命令以下:node
npm install --save-dev enzyme
因为React 项目须要依赖React的一些东西,因此请确保如下模块已经安装。react
npm install --save react react-dom babel-preset-react
要完成渲染测试,除了enzyme以外,还须要Enzyme Adapter库的支持,因为React 版本的不一样,Enzyme Adapter的版本也不同。适配器和React的对应表以下:web
Enzyme Adapter Package | React semver compatibility |
---|---|
enzyme-adapter-react-16 | ^16.0.0 |
enzyme-adapter-react-15 | ^15.5.0 |
enzyme-adapter-react-14.4 | ^15.5.0 |
enzyme-adapter-react-14 | ^0.14.0 |
enzyme-adapter-react-13 | ^0.13.0 |
enzyme支持三种方式的渲染:
shallow:浅渲染,是对官方的Shallow Renderer的封装。将组件渲染成虚拟DOM对象,只会渲染第一层,子组件将不会被渲染出来,于是效率很是高。不须要DOM环境, 并可使用jQuery的方式访问组件的信息;
render:静态渲染,它将React组件渲染成静态的HTML字符串,而后使用Cheerio这个库解析这段字符串,并返回一个Cheerio的实例对象,能够用来分析组件的html结构。
mount:彻底渲染,它将组件渲染加载成一个真实的DOM节点,用来测试DOM API的交互和组件的生命周期,用到了jsdom来模拟浏览器环境。npm
经常使用函数
enzyme中有几个比较核心的函数须要注意,以下:json
- simulate(event, mock):用来模拟事件触发,event为事件名称,mock为一个event object;
- instance():返回测试组件的实例;
- find(selector):根据选择器查找节点,selector能够是CSS中的选择器,也能够是组件的构造函数,以及组件的display name等;
- at(index):返回一个渲染过的对象;
- get(index):返回一个react node,要测试它,须要从新渲染;
- contains(nodeOrNodes):当前对象是否包含参数重点 node,参数类型为react对象或对象数组;
- text():返回当前组件的文本内容;
- html(): 返回当前组件的HTML代码形式;
- props():返回根组件的全部属性;
- prop(key):返回根组件的指定属性;
- state():返回根组件的状态;
- setState(nextState):设置根组件的状态;
- setProps(nextProps):设置根组件的属性;
使用
为了方便讲解Enzyme测试的用法,咱们首先新建一个enzyme.js的测试文件。代码以下:数组
import React from 'react' const Example=(props)=>{ return (<div> <button>{props.text}</button> </div>) } export default Example
浅渲染shallow
前面说过,Shallow Rendering用于将一个组件渲染成虚拟DOM对象,可是只渲染第一层,不渲染全部子组件,因此处理速度很是快。而且它不须要DOM环境,由于根本没有加载进DOM。浏览器
为了进行浅渲染shallow测试,咱们新建一个名为enzyme.test.js的测试文件。服务器
import React from 'react' import Enzyme from 'enzyme' import Adapter from 'enzyme-adapter-react-16' import Example from '../enzyme' const {shallow}=Enzyme Enzyme.configure({ adapter: new Adapter() }) describe('Enzyme shallow', function () { it('Example component', function () { const name='按钮名' let app = shallow(<Example text={name} />) let btnName=app.find('button').text(); console.log('button Name:'+btnName) }) })
执行yarn test命令,会看到以下的运行结果:
babel
为了不每一个测试文件都这么写,咱们能够再test目录下新建一个配置文件enzyme_config.test.js。文件内容以下:
import Enzyme from 'enzyme'; import Adapter from 'enzyme-adapter-react-16'; Enzyme.configure({ adapter: new Adapter(), }); export default Enzyme;
而后,在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" }
如今,咱们的shallow测试代码能够改成:
import React from 'react' import Enzyme from './enzyme.config'; import Example from '../enzyme' const {shallow}=Enzyme describe('Enzyme shallow', function () { it('Example component', function () { const name='按钮名' let app = shallow(<Example text={name} />) let btnName= app.find('button').text() console.log('button Name:'+btnName) }) })
彻底渲染mount
mount渲染用于将React组件加载为真实DOM节点。然而,真实DOM须要一个浏览器环境,为了解决这个问题,咱们能够用到jsdom,也就是说咱们能够用jsdom模拟一个浏览器环境去加载真实的DOM节点。
首先,使用下面的命令安装jsdom模拟浏览器环境,安装命令以下:
npm install --save-dev jsdom
而后咱们添加一个彻底渲染的测试代码:
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}`) buttonObj.text(),spanObj.text() }) })
静态渲染render
render静态渲染,主要用于将React组件渲染成静态的HTML字符串,而后使用Cheerio这个库解析这段字符串,并返回一个Cheerio的实例对象,能够用来分析组件的html结构。针对前面的enzyme.js文件,咱们的静态渲染测试的代码以下:
import React from 'react' import Enzyme from 'enzyme' import Adapter from 'enzyme-adapter-react-16' import Example from '../enzyme' const {shallow,mount,render}=Enzyme Enzyme.configure({ adapter: new Adapter() }) describe('Enzyme render test', function () { it('Example render', 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}`) buttonObj.text(),spanObj.text() }) })
执行上面的代码,测试结果以下:
对比
为了对比这三大测试框架,咱们能够对比看一下:
describe('shallow vs render vs mount', function () { it('测试 shallow 500次', () => { for (let i = 0; i < 500; i++) { const app = shallow(<Example/>) app.find('button').text() } }) it('测试render500次', () => { for (let i = 0; i < 500; i++) { const app = render(<Example/>) app.find('button').text() } }) it('测试mount500次', () => { for (let i = 0; i < 500; i++) { const app = mount(<Example/>) app.find('button').text() } }) })
运行结果以下图:
如上图,shallow是最快的,这是由于shallow的局限性,只渲染第一层,不渲染全部子组件。事实证实,render的效率是mount的两倍。
那么问题来了,mount存在的价值是什么?固然是有价值的,shallow和mount由于都是dom对象的缘故,因此都是能够模拟交互的。
本文同步分享在 博客“xiangzhihong8”(CSDN)。
若有侵权,请联系 support@oschina.cn 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一块儿分享。