# Test Renderer
如何引入
import TestRenderer from 'react-test-renderer'; // ES6
const TestRenderer = require('react-test-renderer'); // ES5 with npm
# 概览
这个 package 提供了一个 React 渲染器,用于将 React 组件渲染成纯 JavaScript 对象,无需依赖 DOM 或原生移动环境。
这个 package 提供的主要功能是在不依赖浏览器或 jsdom 的情况下,返回某个时间点由 React DOM 或者 React Native 平台渲染出的视图结构(类似与 DOM 树)快照。
示例:
import TestRenderer from 'react-test-renderer';
function Link(props) {
  return <a href={props.page}>{props.children}</a>;
}
const testRenderer = TestRenderer.create(
  <Link page="https://www.facebook.com/">Facebook</Link>
);
console.log(testRenderer.toJSON());
// { type: 'a',
//   props: { href: 'https://www.facebook.com/' },
//   children: [ 'Facebook' ] }
你可以使用 Jest 的快照测试功能来自动保存当前 JSON 树结构到一个文件中,并在测试中检查它是否被修改: 了解更多 。
你也可以通过遍历输出来查找特定节点,并对它们进行断言。
import TestRenderer from 'react-test-renderer';
function MyComponent() {
  return (
    <div>
      <SubComponent foo="bar" />
      <p className="my">Hello</p>
    </div>
  )
}
function SubComponent() {
  return (
    <p className="sub">Sub</p>
  );
}
const testRenderer = TestRenderer.create(<MyComponent />);
const testInstance = testRenderer.root;
expect(testInstance.findByType(SubComponent).props.foo).toBe('bar');
expect(testInstance.findByProps({className: "sub"}).children).toEqual(['Sub']);
# TestRenderer
- TestRenderer.create()
- TestRenderer.act()
# 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()
 TestRenderer.create(element, options);
通过传来的 React 元素创建一个 TestRenderer 实例。它并不使用真实的 DOM,但是它依然将组件树完整地渲染到内存,以便于你对它进行断言。此时将返回一个 TestRenderer 实例。
# TestRenderer.act()
 TestRenderer.act(callback);
与 react-dom/test-utils 中的 act() 相似,TestRender.act 为断言准备一个组件。可以使用 act() 来包装 TestRenderer.create 和 testRenderer.update。
import {create, act} from 'react-test-renderer';
import App from './app.js'; // The component being tested
// 渲染组件
let root; 
act(() => {
  root = create(<App value={1}/>)
});
// 对根元素进行断言
expect(root.toJSON()).toMatchSnapshot();
// 更新 props
act(() => {
  root.update(<App value={2}/>);
})
// 对根元素进行断言
expect(root.toJSON()).toMatchSnapshot();
# testRenderer.toJSON()
 testRenderer.toJSON()
返回一个已渲染的的树对象。该树仅包含特定平台的节点,例如 或 和它们的 props,但并不包含任何用户编写的组件。这对于 快照测试 非常方便。
# testRenderer.toTree()
 testRenderer.toTree()
返回一个已渲染的的树对象。它所表示的内容比 toJSON() 提供的内容要更加详细,并且包含用户编写的组件。除非你要在测试渲染器(test renderer)之上编写自己的断言库,否则你可能并不需要这个方法。
# testRenderer.update()
 testRenderer.update(element)
使用新的根元素重新渲染内存中的树。它模拟根元素的一次 React 更新。如果新的元素和之前的元素有相同的 type 和 key,该树将会被更新;否则,它将重挂载一个新树。
# testRenderer.unmount()
 testRenderer.unmount()
卸载内存中的树,会触发相应的生命周期事件。
# testRenderer.getInstance()
 testRenderer.getInstance()
如果可用的话,返回与根元素相对应的实例。如果根元素是函数定义组件,该方法无效,因为函数定义组件没有实例。
# testRenderer.root
 testRenderer.root
返回根元素“测试实例”对象,它对于断言树中的特定节点十分有用。你可以利用它来查找其他更深层的“测试实例”。
# testInstance.find()
 testInstance.find(test)
找到一个 test(testInstance) 返回 true 的后代测试实例。如果不只有一个测试实例匹配,将会报错。
# testInstance.findByType()
 testInstance.findByType(type)
找到匹配指定 type 的后代测试实例,如果不是只有一个测试实例匹配指定的 type,将会报错。
# testInstance.findByProps()
 testInstance.findByProps(props)
找到匹配指定 props的后代测试实例,如果不是正好只有一个测试实例匹配指定的 props,将会报错。
# testInstance.findAll()
 testInstance.findAll(test)
找到所有 test(testInstance) 返回 true 的后代测试实例。
# testInstance.findAllByType()
 testInstance.findAllByType(type)
找到所有匹配指定 type 的后代测试实例。
# testInstance.findAllByProps()
 testInstance.findAllByProps(props)
找到所有匹配指定 props 的后代测试实例。
# testInstance.instance
 testInstance.instance
该测试实例相对应的组件实例。它只能用于类定义组件,因为函数定义组件没有实例。它匹配给定的组件内部的 this 的值。
# testInstance.type
 testInstance.type
该测试实例相对应的组件的类型。例如,一个 `` 组件有一个 Button 类型。
# testInstance.props
 testInstance.props
该测试实例相对应的组件的 props。例如,一个 `` 组件的 props 为 {size: 'small'}。
# testInstance.parent
 testInstance.parent
该测试实例的父测试实例。
# testInstance.children
 testInstance.children
该测试实例的子测试实例。
# 想法
你可以把 createNodeMock 函数作为选项(option)传递给 TestRenderer.create,进行自定义 refs 模拟。createNodeMock 接受当前元素作为参数,并且返回一个模拟 ref 对象的。这十分有利于依赖 refs 组件的测试。
import TestRenderer from 'react-test-renderer';
class MyComponent extends React.Component {
  constructor(props) {
    super(props);
    this.input = null;
  }
  componentDidMount() {
    this.input.focus();
  }
  render() {
    return <input type="text" ref={el => this.input = el} />
  }
}
let focused = false;
TestRenderer.create(
  <MyComponent />,
  {
    createNodeMock: (element) => {
      if (element.type === 'input') {
        // 模拟 focus 函数
        return {
          focus: () => {
            focused = true;
          }
        };
      }
      return null;
    }
  }
);
expect(focused).toBe(true);