React 是一个流行的 JavaScript 库,用于构建复杂的用户界面。它的组件化设计使得开发人员可以轻松地构建可重用的组件。然而,在构建大型应用时,确保组件的正确性变得至关重要。这就是测试所涉及到的领域。在这篇文章中,我们将重点介绍使用 Enzyme 进行 React 组件测试的最佳实践。
Enzyme 是什么?
Enzyme 是一个 React 测试工具库,它提供了一组 API,用于在测试中模拟 React 组件并在其上执行断言。Enzyme 支持多种模拟组件的方式,包括浅层渲染(shallow)、完全渲染(mount)和静态页面生成(render)。这使得开发人员可以在一个虚拟 DOM 中测试组件的用户交互、状态和事件处理。
测试 React 组件的目的
在编写应用程序时,测试是不可或缺的一部分。例如,在编写 React 组件时,您可能会遇到以下几种情况:
- 组件在接收正确的属性(props)时对渲染做出正确的决策。
- 组件对用户操作的响应是正确的。
- 组件在状态改变时呈现正确的表现。
- 组件权威地处理异步操作和回调。
这些都是可测试的场景,并且会帮助您在某些情况下捕捉错误。
一个基本测试用例
在本教程的后面,我们将进一步深入了解如何使用 Enzyme 来测试 React 组件。让我们从一个简单的测试用例开始,我们要测试的组件是一个简单的按钮。
// button.jsx import React from 'react' const Button = ({ label }) => { return <button>{ label }</button> } export default Button
此组件接受一个 label 属性,并呈现一个带有该标签文本的 Button 元素。我们将创建一个测试文件用于测试 Button 组件。
// javascriptcn.com 代码示例 // button.test.js import React from 'react' import { shallow } from 'enzyme' import Button from './button' describe('Button', () => { test('renders a label', () => { const wrapper = shallow(<Button label="Click me" />) expect(wrapper.text()).toEqual('Click me') }) })
在这个简单的测试用例中,我们首先将 React 和 Enzyme 导入测试文件中。由于我们只需要测试 Button 的渲染结果,我们选择了浅层渲染。我们创建了一个 Enzyme 测试实例 wrapper 并传递一个包含 label 属性的 Button 组件。我们最终使用 expect 函数编写断言以验证测试结果是否符合预期。
如何测试用户交互
测试用户的行为可以用于检查组件的状态等属性。我们将使用 mount() 方法来完全渲染组件,并在模拟单击操作时检查组件状态的变化。
// javascriptcn.com 代码示例 // incrementBtn.jsx import React, { Component } from 'react' class IncrementBtn extends Component { state = { count: 0 } handleClick = () => { this.setState(prevState => ({ count: prevState.count + 1 })) } render() { return ( <button onClick={this.handleClick}>{this.state.count}</button> ) } } export default IncrementBtn
这是一个 IncrementBtn 组件,每当我们单击按钮时,它将增加 stat 中的 count 状态。我们来编写一个测试用例,该测试用例会在单击按钮时增加计数器值并检查是否呈现了正确的结果。
// javascriptcn.com 代码示例 // incrementBtn.test.js import React from 'react' import { mount } from 'enzyme'; import IncrementBtn from './incrementBtn'; describe('IncrementBtn', () => { test('increments count on button click', () => { const wrapper = mount(<IncrementBtn />) const button = wrapper.find('button') button.simulate('click') expect(wrapper.state().count).toBe(1) expect(wrapper.text()).toEqual('1') }); });
在此测试用例中,我们使用 mount() 方法创建了一个完整的渲染实例,并使用 find() 方法获取到按钮元素。我们然后通过 simulate() 方法将单击事件传递到按钮元素。最终,我们编写了两个断言来验证计数器和组件文本内容是否正确。在这个简单的例子中,我们已经成功地测试了一个用户交互场景。
如何测试异步操作
React 组件通常会涉及异步事件,例如网络请求或回调函数等。这些场景需要特殊处理,以确保测试的正确性。
考虑以下代码,该代码在数据加载时显示一个加载中的消息。
// javascriptcn.com 代码示例 // data.jsx import React, { Component } from 'react' class Data extends Component { state = { data: null, loading: true } componentDidMount() { fetch('/api/data') .then(res => res.json()) .then(data => this.setState({ data, loading: false })) } render() { const { data, loading } = this.state if (loading) return 'Loading...' return <div>{data}</div> } } export default Data
我们将编写一个测试用例,该测试用例将模拟响应并验证组件状态是否正确设置。
// javascriptcn.com 代码示例 // data.test.js import React from 'react' import { mount } from 'enzyme'; import Data from './data'; describe('Data', () => { test('renders fetched data after api call', done => { const data = 'Hello World' global.fetch = jest.fn(() => Promise.resolve({ json: () => Promise.resolve(data) }) ) const wrapper = mount(<Data />) process.nextTick(() => { expect(wrapper.state().data).toEqual(data) expect(wrapper.text()).toEqual(data) done() }) }) });
在此测试用例中,我们首先将 fetch() 方法模拟为返回一个 Promise,该 Promise 将在后续的测试中使用。然后我们使用 Enzyme 的 mount() 方法创建一个完整的渲染实例。
最后,我们通过在 process.nextTick() 方法中运行断言来等待异步操作完成。该方法允许我们在状态发生变化之后,再次运行验证逻辑。当异步操作完成时,我们会断言相应的状态和呈现的数据是否正确,并且最终调用 done() 函数。
总结
在本文中,我们了解了 Enzyme 的三种测试方式(浅层、完全和静态渲染),并实现了一些常见场景的测试用例。我们学习了如何进行用户交互和异步操作的测试,对于正常运行的应用程序,这两种情况非常常见。
使用 Enzyme 可以让你轻松测试 React 应用程序。通过模拟您的组件并在其上执行断言,您可以确保组件在各种情况下都有正确的行为,并帮助您捕捉潜在的错误。
来源:JavaScript中文网 ,转载请注明来源 本文地址:https://www.javascriptcn.com/post/653d0d317d4982a6eb6f3aa5