此文章是翻译Test Renderer这篇React(版本v16.2.0)官方文档。

Test Renderer

Importing

  1. import TestRenderer from 'react-test-renderer'; // ES6
  2. const TestRenderer = require('react-test-renderer'); // ES5 with npm

概览

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

本质上,该包可以在无需使用浏览器或jsdom 的情况下,轻松地抓取由React DOM 或React Native 组件渲染出的平台视图层次结构(类似于DOM树)快照。

例如:

  1. import TestRenderer from 'react-test-renderer';
  2. function Link(props) {
  3. return <a href={props.page}>{props.children}</a>
  4. }
  5. const testRenderer = TestRederer.create(
  6. <Link page="https://www.facebook.com/">Facebook</Link>
  7. );
  8. console.log(testRenderer.toJSON());
  9. // { type: 'a',
  10. // props: { href: 'https://www.facebook.comm/' },
  11. // children: [ 'Facebook' ]}

你可以使用Jest 的快照测试功能来自动保存一个该JSON 树文件的副本,并且在你的测试中检查它是否被更改。了解更多

你也可以通过遍历输出去查找特殊节点,进行断言。

  1. import TestRenderer from 'react-test-renderer';
  2. function MyComponent() {
  3. return (
  4. <div>
  5. <SubComponent foo="bar" />
  6. <p className="my">Hello</p>
  7. </div>
  8. )
  9. }
  10. function SubComponent() {
  11. return (
  12. <div>
  13. <p className="sub">Sub</p>
  14. </div>
  15. )
  16. }
  17. const testRenderer = TestRederer.create(<MyComponent />);
  18. const testInstance = testRenderer.root;
  19. expect(testInstance.findByType(SubComponent).props.foo).toBe('bar');
  20. expect(testInstance.findByProps({className: "sub"}).children).toEqual(['Sub']);

TestRenderer

  • TestRenderer.create()

TestRenderer instance

  • testRenderer.toJSON()
  • testRenderer.toTree()
  • testRenderer.update()
  • testRenderer.unmount()
  • testRenderer.getInstance()
  • testRenderer.root

testInstance

  • testInstance.find()
  • testInstance.findByType()
  • testInstance.findByProps()
  • testInstance.findAll()
  • testInstance.findAllByType()
  • testInstance.findAllByProps()
  • testInstance.instance
  • testInstance.type
  • testInstance.props
  • testInstance.parent
  • testInstance.children

参考

TestRenderer.create()

  1. TestRenderer.create(element, options);

通过传来的React 元素创建一个TestRenderer 的实例。它并不使用真实的DOM,但是它依然将组件树完整地渲染到内存,所以你可以对它进行断言。返回的实例拥有以下的方法和属性。

testRenderer.toJSON()

  1. testRenderer.toJSON()

返回一个表示渲染后的树的对象。该树仅包含特定平台的节点,像<div><View> 和他们的属性(props),但是并不包含任何用户编写的组件。这对于快照测试非常方便。

testRenderer.toTree()

  1. testRenderer.toTree()

返回一个表示渲染后的树的对象。不同于toJSON() ,它表示的内容比toJSON() 提供的内容要更加详细,并且包含用户编写的组件。除非您正在测试渲染器(test rendererer)之上编写你自己的断言库,否则你可能并不需要这个方法。

testRenderer.update()

  1. testRenderer.update(element)

使用新的根元素重新渲染内存中的树。它模拟根元素的一次React更新。如果新的元素和之前的元素有相同的type 和key,该树将会被更新;否则,它将重挂载一个新树。

testRenderer.unmount()

  1. testRenderer.unmount()

卸载内存中的树,触发相应的生命周期事件。

testRenderer.getInstance()

  1. testRenderer.getInstance()

返回与根元素相对应的实例, 如果可用的话。如果根元素是函数组件,该方法无效,因为函数组件没有实例。

testRenderer.root

  1. testRenderer.root

返回根元素“测试实例”对象,对于断言树中的特殊节点十分有用。你可以使用它来查找其他更深层的“测试实例”。

testInstance.find()

  1. testInstance.find(test)

找到一个test(testInstance) 返回true 的后代测试实例。如果test(testInstance) 没有对一个明确的测试实例返回true ,将会报错。

testInstance.findByType()

  1. testInstance.findByType(type)

找到一个匹配指定type 的后代测试实例,如果没有匹配指定的type 的一个测试实例,将会报错。

testInstance.findByProps()

  1. testInstance.findByProps(props)

找到一个匹配指定props 的后代测试实例,如果没有匹配指定的props 的一个测试实例,将会报错。

testInstance.findAll()

  1. testInstance.findAll(test)

找到所有的test(testInstance) 返回true 的后代测试实例。

testInstance.findAllByType()

  1. testInstance.findAllByType(type)

找到所有的匹配指定type 的后代测试实例。

testInstance.findAllByProps()

  1. testInstance.findAllByProps(props)

找到所有的匹配指定props 的后代测试实例。

testInstance.instance

  1. testInstance.instance

该测试实例相对应的组件实例。它只能用于类组件,因为函数组件没有实例。它匹配给定的组件内部的 this 的值。

testInstance.type

  1. testInstance.type

该测试实例相对应的组件的type,例如,<Button /> 组件有Button type。

testInstance.props

  1. testInstance.props

该测试实例相对应的props,例如,<Button size="small" /> 组件有{size: 'small'} 作为props。

testInstance.parent

  1. testInstance.parent

该测试实例的父测试实例。

testInstance.children

  1. testInstance.children

该测试实例的子测试实例。

思考

你可以将createNodeMock 函数作为option 传递给TestRenderer.create,可以自行模拟refs。createNodeMock 接受当前元素作为参数,应该返回一个模拟的 ref 对象。当你要测试一个依赖于refs 的组件时,它十分有用。

  1. import TestRederer from 'react-test-renderer';
  2. class MyComponent extends React.Component {
  3. constructor(props) {
  4. super(props);
  5. this.input = null;
  6. }
  7. componentDidMount() {
  8. this.input.focus();
  9. }
  10. render() {
  11. return <input type="text" ref={el => this.input = el} />
  12. }
  13. }
  14. let focused = false;
  15. TestRenderer.create(
  16. <MyComponent />,
  17. {
  18. createNodeMock: (element) => {
  19. if (elementy.type === 'input') {
  20. // mock a focus function
  21. return {
  22. focus: () => {
  23. focusd = true;
  24. }
  25. };
  26. }
  27. return null;
  28. }
  29. }
  30. );
  31. expect(focused).toBe(true);