首页 > 解决方案 > 如何使用 react-testling-library 测试反应功能组件是否重新渲染

问题描述

我正在开发一个包含大量子组件垂直列表的应用程序。每个子组件都在使用React.memo,并且我已经构建了优化以确保当列表中的其他组件被修改并更新组件树中更高的状态时它们不会重新渲染。

这运行良好并且具有显着的性能改进,但是我想编写单元测试以防止未来的回归,因为项目中的人们添加了更多的功能、道具、状态等。

理想情况下,我想渲染父组件和其中一些子组件,并对一个只导致父组件和那个子组件重新渲染的操作执行操作。然后我想测试其他子组件是否不会重新渲染。这将是一项安全测试,以确保人们不会做出破坏React.memo(匿名功能或新对象作为道具等)的更改。

这是层次结构的粗略描述:

function Parent() {
  const [state, setState] = useState({});
  const items = queryItems();


  return (
    <div>
        {items.map((item) => <Child key={item.id} item={item} setState={setState} />)}
    <div>
  );
}


const Child = React.memo(function({item, setState}) {
   const handleClick = () => {
      // Does something to update state
      setState({something: 'changed'});
   };

   return (
       <div>
          {item.title}
          <button onClick={handleClick} />
       </div>
   );
});

如果有人进来并将.map逻辑更改为:

{items.map((item) => <Child key={item.id} item={item} setState={setState} otherProp={{}} />)}

添加为 otherProp 的对象会破坏React.memo并导致所有子级在每次父级渲染时重新渲染。如果有人导致这样的回归,我如何编写测试以确保它会失败?(我们有 jest、react-testing-library 和可用的酵素)

标签: javascriptreactjsenzymereact-testing-library

解决方案


  • 您可以尝试的一件事是将孩子包裹在带有计数器道具的 HOC 中,以查看它是否呈现了孩子,但我不确定这是否适用于备忘录。

  • 您可以尝试 jest 的 spyon 模拟对象https://jestjs.io/docs/jest-object,但是我再次不确定这是否适用于备忘录,因为它可能会触发模拟对象上的重新渲染它不会有对备忘录孩子这样做。

  • 当您进入此类测试领域时,您可能必须仔细考虑是否仍在进行单元测试。优化、负载平衡、压力测试、组件如何与其他组件交互以及类似的想法都属于集成测试领域,正如您对问题的评论中提到的那样。理想情况下,您应该只测试量化的可重用代码或组件,而不是它们如何相互交互,但这又是一个灰色区域,因为父级与其自己的子级相关。但是,在这种情况下,我认为测试它是否重新渲染不适用于单元测试。

  • 我相信你最好的选择就是相信如果你传递了相同的道具并且如果应用了备忘录,孩子不会重新渲染,在这种情况下你不必关心它是否被重新渲染,而是你可以测试传递给它的道具是否仍然相同,并由此得出结论,它不会重新渲染。而是测试道具本身而不是渲染。


推荐阅读