测试React组件指南

React是在JavaScript开发人员社区中取得长足发展的框架。 React具有用于设计组件的强大组成框架。 React组件是一些可重用的代码,您可以在Web应用程序中使用它们。

React组件不是与DOM紧密耦合的,但是它们进行单元测试有多容易? 在本文中,让我们探索对单元进行React组件的测试。 我将展示使您的组件可测试的思考过程。

请记住,我只是在谈论单元测试 ,这是一种特殊的测试。 (有关各种测试的更多信息,我建议您阅读“ JavaScript测试:单元测试,功能测试和集成测试 ”。)

对于单元测试,我对两件事感兴趣:快速反馈和令人讨厌的反馈。 这样,我可以以高度的置信度和代码质量遍历更改。 这使您可以放心,您的React组件不会落在浏览器上。 快速获得良好反馈的能力为您提供了竞争优势-在当今的敏捷软件开发世界中,您将希望保持这一优势。

对于演示,让我们列出大猿的列表,可以通过复选框对其进行过滤。 您可以在GitHub上找到整个代码库。 为了简洁起见,我仅显示感兴趣的代码示例。 本文假设您具有React组件的知识水平。

如果您下载并运行演示示例代码,则会看到如下页面:

React Components中的大猿人演示

编写可测试的组件

在React中,一个好的方法是从组件的层次结构开始。 构建每个单独的组件时会想到单一责任原则 。 React组件使用对象组成和关系。

例如,对于大猩猩列表,我有以下方法:

FilterableGreatApeList
|_ GreatApeSearchBar
|_ GreatApeList
   |_ GreatApeRow

看一看伟大的猿猴列表如何有许多伟大的猿猴行与数据。 React组件利用了这种成分数据模型,并且也是可测试的。

在React组件中,避免使用继承来构建可重用的组件。 如果您来自经典的面向对象编程背景,请记住这一点。 React组件不提前知道其子级。 测试源自一长串祖先的组件可能是一场噩梦。

我将让您自己探索FilterableGreatApeList 。 这是一个React组件,这里有两个单独的组件。 也可以随意探索它附带的单元测试。

例如,要构建可测试的GreatApeSearchBar ,请执行以下操作:

class GreatApeSearchBar extends Component {
  constructor(props) {
    super(props);

    this.handleShowExtantOnlyChange = this.handleShowExtantOnlyChange.bind(this);
  }

  handleShowExtantOnlyChange(e) {
    this.props.onShowExtantOnlyInput(e.target.checked);
  }

  render() {
    return(
      <form>
        <input
          id="GreatApeSearchBar-showExtantOnly"
          type="checkbox"
          checked={this.props.showExtantOnly}
          onChange={this.handleShowExtantOnlyChange}
        />

        <label htmlFor="GreatApeSearchBar-showExtantOnly">Only show extant species</label>
      </form>
    );
  }
}

该组件具有一个带有标签的复选框,并连接一个click事件。 您可能已经对这种方法太熟悉了,这是非常好的事情。

请注意,使用React,可立即使用的可测试组件是免费的。 这里没有什么特别的-事件处理程序,JSX和render方法。

层次结构中的下一个React组件是GreatApeList ,它看起来像这样:

class GreatApeList extends Component {
  render() {
    let rows = [];

    this.props.apes.forEach((ape) => {
      if (!this.props.showExtantOnly) {
        rows.push(<GreatApeRow key={ape.name} ape={ape} />);

        return;
      }

      if (ape.isExtant) {
        rows.push(<GreatApeRow key={ape.name} ape={ape} />);
      }
    });

    return (
      <div>
        {rows}
      </div>
    );
  }
}

这是一个具有GreatApeRow组件的React组件,它使用的是对象组合。 这是React工作中最强大的组合模型。 请注意,在构建可重用但可测试的组件时缺少继承。

在编程中, 对象组合是一种启用数据驱动元素的设计模式。 换句话说,一个GreatApeList有许多GreatApeRow对象。 UI组件之间的这种关系驱动了设计。 React组件内置了这种思维方式。通过这种查看UI元素的方式,您可以编写一些不错的单元测试。

在这里,您检查来自复选框的this.props.showExtantOnly标志。 这个showExtantOnly属性是通过GreatApeSearchBar的事件处理程序GreatApeSearchBar

对于单元测试,如何对依赖其他组件的React组件进行单元测试? 组件相互缠绕如何? 这些是我们即将进行测试时要记住的重要问题。 React组件可能还具有可以解锁的秘密。

现在,让我们看一下GreatApeRow ,其中包含了很棒的猿数据:

class GreatApeRow extends Component {
  render() {
    return (
      <div>
        <img
          className="GreatApeRow-image"
          src={this.props.ape.image}
          alt={this.props.ape.name}
        />

        <p className="GreatApeRow-detail">
          <b>Species:</b> {this.props.ape.name}
        </p>

        <p className="GreatApeRow-detail">
          <b>Age:</b> {this.props.ape.age}
        </p>
      </div>
    );
  }
}

使用React组件,将每个UI元素隔离在一个关注点上非常实用。 在单元测试方面,这具有关键优势。 只要坚持这种设计模式,就可以无缝编写单元测试。

测试工具

让我们回顾一下测试React组件时的最大担忧。 如何隔离地对单个组件进行单元测试? 好吧,事实证明,有一个漂亮的实用程序使您能够做到这一点。

React中的Shallow Renderer允许您将组件深一层渲染。 由此,您可以断言render方法的作用。 引人注目的是它不需要DOM。

使用ES6,您可以像这样使用它:

import ShallowRenderer from 'react-test-renderer/shallow';

为了使单元测试快速运行,您需要一种隔离测试组件的方法。 这样,您可以专注于单个问题,对其进行测试,然后继续处理下一个问题。 随着解决方案的发展,这将成为强大的力量,您可以随意进行重构-紧跟代码,进行快速更改,并获得保证,它将在浏览器中运行。

这种方法的优点之一是您可以更好地考虑代码。 这产生了解决当前问题的最佳解决方案。 当您不束手无策时,我发现它解放了。 人脑在一次处理多个问题上做得很糟糕。

剩下的唯一问题是,这个小工具可以带我们使用React组件多远?

放在一起

看一下GreatApeList 。 您要解决的主要问题是什么? 此组件根据过滤器向您显示大猩猩列表。

一个有效的单元测试是传递一个列表并检查有关此React组件做什么的事实。 我们要确保它根据标志过滤大猿。

一种方法是这样做:

import GreatApeList from './GreatApeList';

const APES = [{ name: 'Australopithecus afarensis', isExtant: false },
  { name: 'Orangutan', isExtant: true }];

// Arrange
const renderer = new ShallowRenderer();
renderer.render(<GreatApeList
  apes={APES}
  showExtantOnly={true} />);

// Act
const component = renderer.getRenderOutput();
const rows = component.props.children;

// Assert
expect(rows.length).toBe(1);

请注意,我正在使用Jest测试React组件。 有关更多信息,请查看“ 如何使用Jest测试React组件 ”。

在JSX中,查看showExtantOnly={true} 。 JSX语法允许您为React组件设置状态。 这为给定特定状态的组件测试提供了许多方法。 JSX理解基本的JavaScript类型,因此将true标志设置为布尔值。

GreatApeSearchBar了清单, GreatApeSearchBar怎么GreatApeSearchBar ? 它可能在onChange属性中具有此事件处理程序,可能对此感兴趣。

一个好的单元测试就是这样做:

import GreatApeSearchBar from './GreatApeSearchBar';

// Arrange
let showExtantOnly = false;
const onChange = (e) => { showExtantOnly = e };

const renderer = new ShallowRenderer();
renderer.render(<GreatApeSearchBar
  showExtantOnly={true}
  onShowExtantOnlyInput={onChange} />);

// Act
const component = renderer.getRenderOutput();
const checkbox = component.props.children[0];

checkbox.props.onChange({ target: { checked: true } });

// Assert
expect(showExtantOnly).toBe(true);

要处理和测试事件,请使用相同的浅表呈现方法。 getRenderOutput方法对于将回调函数绑定到具有事件的组件很有用。 在这里,为onShowExtantOnlyInput属性分配了回调onChange函数。

在更简单的单元测试中, GreatApeRow React组件又如何呢? 它使用HTML标记显示出色的猿类信息。 事实证明,您也可以使用浅色渲染器来测试此组件。

例如,确保我们渲染图像:

import GreatApeRow from './GreatApeRow';

const APE = {
  image: 'https://en.wikipedia.org/wiki/File:Australopithecus_afarensis.JPG',
  name: 'Australopithecus afarensis'
};

// Arrange
const renderer = new ShallowRenderer();
renderer.render(<GreatApeRow ape={APE} />);

// Act
const component = renderer.getRenderOutput();
const apeImage = component.props.children[0];

// Assert
expect(apeImage).toBeDefined();
expect(apeImage.props.src).toBe(APE.image);
expect(apeImage.props.alt).toBe(APE.name);

对于React组件,所有这些都围绕着render方法。 这使得确切地知道您需要测试的内容有些直观。 较浅的渲染器使它成为可能,因此您可以激光聚焦在单个组件上,同时消除噪声。

结论

如图所示,React组件非常容易测试。 没有放弃为组件编写好的单元测试的借口。

令人高兴的是,JSX在每个单独的测试中都能为您工作,而不是不利于您。 使用JSX,您可以传入布尔值,回调或其他任何您需要的东西。 当您冒险自己进行单元测试React组件时,请记住这一点。

浅浅的渲染器测试实用程序为您提供了良好的单元测试所需的一切。 它仅渲染一个级别的深度,并允许您隔离测试。 您不必担心层次结构中可能破坏单元测试的任何子级。

使用Jest工具,我喜欢它如何仅向您提供您要更改的特定文件的反馈。 这缩短了反馈回路并增加了激光聚焦。 我希望您看到当您解决一些棘手的问题时,这将是多么有价值。

From: https://www.sitepoint.com/testing-react-components/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值