@xiaoqq
2018-10-29T14:09:35.000000Z
字数 3369
阅读 847
React
Jest 被 Facebook 用来测试包括 React 应用在内的所有 JavaScript 代码。
匹配器
每次要测试一个值时都会使用expect函数,通过matcher来断言某个值。
expect('team').not. 取反
Matcher
.toBe(value) 判断两个值类型是否相等
.toEqual(value) 可以判断两个对象是否相等
.toMatch(regexpOrString) 使用正则表达式匹配
.toBeCloseTo(number, numDigits)
.toBeNull()
.toBeTruthy()
.toBeUndefined()
异步代码
异步的测试只能使用Promise来解决
test('the fetch fails with an error', () => {
expect.assertions(1);
return expect(fetchData()).rejects.toMatch('error');
});
assertions(1)代表的是在当前的测试中至少有一个断言是被调用的,否则判定为失败。
当然,还可以使用Async/Await的方式来简化编写
test('the data is peanut butter', async () => {
expect.assertions(1);
const data = await fetchData();
expect(data).toBe('peanut butter');
});
test('the fetch fails with an error', async () => {
expect.assertions(1);
try {
await fetchData();
} catch (e) {
expect(e).toMatch('error');
}
});
准备工作和测试后整理工作
React官方一共提供了三个库
这个库里面有一些工具方法
a) ReactTestUtils.renderIntoDocument
: 将元素渲染到DOM节点中,要求使用jsdom
源码:
renderIntoDocument: function (element) {
var div = document.createElement('div');
// None of our tests actually require attaching the container to the
// DOM, and doing so creates a mess that we rely on test isolation to
// clean up, so we're going to stop honoring the name of this method
// (and probably rename it eventually) if no problems arise.
// document.documentElement.appendChild(div);
return ReactDOM.render(element, div);
},
b) isElement
isDOMComponent
isCompositeComponent
判断元素类型
c) findRenderedDOMComponentWithTag
等 找到DOM元素
import React from 'react'
import ReactTestUtils from 'react-dom/test-utils'
import { Button } from '@msfe/mui-core'
test('renders correctly', () => {
const node = <Button>test</Button>
let nodeTestResult = ReactTestUtils.isElement(node) // React Element
expect(nodeTestResult).toBeTruthy()
let instance = ReactTestUtils.renderIntoDocument(node) // React Component Instance
let instanceTestResult = ReactTestUtils.isCompositeComponent(instance)
expect(instanceTestResult).toBeTruthy()
let dom = ReactTestUtils.findRenderedDOMComponentWithTag(instance, 'button') // DOM
let domTestResult = ReactTestUtils.isDOMComponent(dom)
expect(domTestResult).toBeTruthy()
})
如果一个组件已经加载进入DOM,react-dom模块的findDOMNode方法会返回该组件所对应的DOM节点。
import {findDOMNode} from 'react-dom';
const appDOM = findDOMNode(instance)
浅层渲染使你可以渲染 “单层深度” 的组件,并且对组件的 render 方法的返回值进行断言,不用担心子组件的行为,组件并没有实例化或被渲染。浅渲染并不需要 DOM。
a) shallowRenderer.render()
你可以把 shallowRenderer 想象成一个用来渲染你正在测试的组件的“地方”,并且你可以从那里取到该组件的输出。
shallowRenderer.render() 和 ReactDOM.render()很像。但是它不需要 DOM 并且只渲染一层。这就意味着你可以测试与子组件行为隔离的组件。
渲染完成之后,使用getRenderOutput()
获取渲染的输出
b) getMountedInstance
获取组件instance,然后可以使用这个intance来调用react一些特殊的方法,比如: setState
, forceUpdate
等
c) unmount
test('ShallowRenderer', () => {
const renderer = new ShallowRenderer()
renderer.render(<Button>test</Button>)
const result = renderer.getRenderOutput() //还是一个React.element
expect(result.type).toBe('button')
})
比较好的例子:
该包提供了一个React的渲染器,可以用来将 React 组件渲染成纯 JavaScript 对象,不需要依赖于 DOM 和原生移动环境。
a) testRenderer.toJSON()
返回渲染后的树对象
b) testRenderer.root
返回根元素“测试实例(test instance)”对象
a) testInstance.find()
Jest快照渲染就是使用这个方法。
DEMO:
test('TestRenderer', () => {
const node = <Button>test</Button> // React Element
const testRenderer = TestRenderer.create(node)
console.log(testRenderer.toJSON())
expect(testRenderer.toJSON()).toMatchSnapshot()
})
比较好的例子: