react测试组件
React是在JavaScript开发人员社区中取得长足发展的框架。 React具有用于设计组件的强大组成框架。 React组件是您可以在Web应用程序中使用的可重用代码的一部分。
React组件不是与DOM紧密耦合的,但是它们进行单元测试有多容易? 在本文中,让我们探索对单元进行React组件的测试。 我将展示使您的组件可测试的思考过程。
请记住,我只是在谈论单元测试 ,这是一种特殊的测试。 (有关各种测试的更多信息,我建议您阅读“ JavaScript测试:单元测试,功能测试和集成测试 ”。)
对于单元测试,我对两件事感兴趣:快速反馈和令人讨厌的反馈。 这样,我可以以高度的置信度和代码质量遍历更改。 这使您可以放心,您的React组件不会落在浏览器上。 快速获得良好反馈的能力为您提供了竞争优势-在当今的敏捷软件开发世界中,您将希望保持这一优势。
对于演示,让我们列出大猿的列表,可以通过复选框对其进行过滤。 您可以在GitHub上找到整个代码库。 为了简洁起见,我仅显示感兴趣的代码示例。 本文假定您具有使用React组件的知识水平。
如果您下载并运行演示示例代码,则会看到如下页面:
编写可测试的组件
在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
。
免费学习PHP!
全面介绍PHP和MySQL,从而实现服务器端编程的飞跃。
原价$ 11.95 您的完全免费
对于单元测试,如何对依赖其他组件的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工具,我喜欢它如何仅向您提供您要更改的特定文件的反馈。 这缩短了反馈回路并增加了激光聚焦。 我希望您看到当您解决一些棘手的问题时,这将是多么有价值。
react测试组件