[关闭]
@xiaoqq 2018-10-29T14:09:35.000000Z 字数 3369 阅读 847

React 单元测试

React


一、Jest

Jest 被 Facebook 用来测试包括 React 应用在内的所有 JavaScript 代码。

  1. 匹配器
    每次要测试一个值时都会使用expect函数,通过matcher来断言某个值。
    expect('team').not. 取反

  2. Matcher
    .toBe(value) 判断两个值类型是否相等
    .toEqual(value) 可以判断两个对象是否相等
    .toMatch(regexpOrString) 使用正则表达式匹配
    .toBeCloseTo(number, numDigits)
    .toBeNull()
    .toBeTruthy()
    .toBeUndefined()

  3. 异步代码
    异步的测试只能使用Promise来解决

    1. test('the fetch fails with an error', () => {
    2. expect.assertions(1);
    3. return expect(fetchData()).rejects.toMatch('error');
    4. });

    assertions(1)代表的是在当前的测试中至少有一个断言是被调用的,否则判定为失败。
    当然,还可以使用Async/Await的方式来简化编写

    1. test('the data is peanut butter', async () => {
    2. expect.assertions(1);
    3. const data = await fetchData();
    4. expect(data).toBe('peanut butter');
    5. });
    6. test('the fetch fails with an error', async () => {
    7. expect.assertions(1);
    8. try {
    9. await fetchData();
    10. } catch (e) {
    11. expect(e).toMatch('error');
    12. }
    13. });
  4. 准备工作和测试后整理工作

二、React 官方单测库

React官方一共提供了三个库

1. react-dom/test-utils 建议使用Enzyme替代之

这个库里面有一些工具方法
a) ReactTestUtils.renderIntoDocument: 将元素渲染到DOM节点中,要求使用jsdom
源码:

  1. renderIntoDocument: function (element) {
  2. var div = document.createElement('div');
  3. // None of our tests actually require attaching the container to the
  4. // DOM, and doing so creates a mess that we rely on test isolation to
  5. // clean up, so we're going to stop honoring the name of this method
  6. // (and probably rename it eventually) if no problems arise.
  7. // document.documentElement.appendChild(div);
  8. return ReactDOM.render(element, div);
  9. },

b) isElement isDOMComponent isCompositeComponent 判断元素类型

c) findRenderedDOMComponentWithTag等 找到DOM元素

渲染React组件

  1. import React from 'react'
  2. import ReactTestUtils from 'react-dom/test-utils'
  3. import { Button } from '@msfe/mui-core'
  4. test('renders correctly', () => {
  5. const node = <Button>test</Button>
  6. let nodeTestResult = ReactTestUtils.isElement(node) // React Element
  7. expect(nodeTestResult).toBeTruthy()
  8. let instance = ReactTestUtils.renderIntoDocument(node) // React Component Instance
  9. let instanceTestResult = ReactTestUtils.isCompositeComponent(instance)
  10. expect(instanceTestResult).toBeTruthy()
  11. let dom = ReactTestUtils.findRenderedDOMComponentWithTag(instance, 'button') // DOM
  12. let domTestResult = ReactTestUtils.isDOMComponent(dom)
  13. expect(domTestResult).toBeTruthy()
  14. })

通过findDOMNode返回对应的节点

如果一个组件已经加载进入DOM,react-dom模块的findDOMNode方法会返回该组件所对应的DOM节点。

  1. import {findDOMNode} from 'react-dom';
  2. const appDOM = findDOMNode(instance)

2. 浅层渲染(Shallow Renderer)

浅层渲染使你可以渲染 “单层深度” 的组件,并且对组件的 render 方法的返回值进行断言,不用担心子组件的行为,组件并没有实例化或被渲染。浅渲染并不需要 DOM。

a) shallowRenderer.render() 你可以把 shallowRenderer 想象成一个用来渲染你正在测试的组件的“地方”,并且你可以从那里取到该组件的输出。

shallowRenderer.render() 和 ReactDOM.render()很像。但是它不需要 DOM 并且只渲染一层。这就意味着你可以测试与子组件行为隔离的组件。

渲染完成之后,使用getRenderOutput()获取渲染的输出

b) getMountedInstance 获取组件instance,然后可以使用这个intance来调用react一些特殊的方法,比如: setStateforceUpdate

c) unmount

  1. test('ShallowRenderer', () => {
  2. const renderer = new ShallowRenderer()
  3. renderer.render(<Button>test</Button>)
  4. const result = renderer.getRenderOutput() //还是一个React.element
  5. expect(result.type).toBe('button')
  6. })

更多用例参考React官方库

比较好的例子:

3. 测试渲染(Test Renderer)

该包提供了一个React的渲染器,可以用来将 React 组件渲染成纯 JavaScript 对象,不需要依赖于 DOM 和原生移动环境。

① test render方法:

a) testRenderer.toJSON() 返回渲染后的树对象
b) testRenderer.root 返回根元素“测试实例(test instance)”对象

② test instance对象方法:

a) testInstance.find()

Jest快照渲染就是使用这个方法。

DEMO:

  1. test('TestRenderer', () => {
  2. const node = <Button>test</Button> // React Element
  3. const testRenderer = TestRenderer.create(node)
  4. console.log(testRenderer.toJSON())
  5. expect(testRenderer.toJSON()).toMatchSnapshot()
  6. })

更多用例参考React官方库

比较好的例子:

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注