Enzyme 是一个流行的 JavaScript 测试工具,它允许开发者在 React 应用程序中进行功能和集成测试,而无需实际渲染组件。它提供了一个易于使用的 API,可用于模拟和操作 React 组件。在本文中,我们将介绍如何使用 Enzyme 来测试您的 React 应用程序。
环境搭建
在开始测试之前,你需要安装以下软件:
- Node.js:建议使用最新的 Long-Term Support 版本。
- Yarn 或者 npm:用于管理依赖项。
- React:一个可独立运行的 React 应用程序,可以是您正在开发的任何项目。
您需要在项目根目录下执行以下命令:
# 使用 Yarn 安装 Enzyme 和相关依赖项 yarn add --dev enzyme @wojtekmaj/enzyme-adapter-react-17 # 使用 npm 安装 Enzyme 和相关依赖项 npm install --save-dev enzyme @wojtekmaj/enzyme-adapter-react-17
接下来,您需要创建一个名为 setupTests.js
的文件,该文件将在测试时自动运行。我们将在其中配置 Enzyme:
// setupTests.js import { configure } from 'enzyme'; import Adapter from '@wojtekmaj/enzyme-adapter-react-17'; configure({ adapter: new Adapter() });
最后,在 package.json
文件中添加以下脚本:
{ "scripts": { "test": "jest" } }
现在,我们已经准备好使用 Enzyme 进行 React 测试!
测试组件
让我们从简单的组件开始。我们将测试一个名为 Button
的组件,该组件根据传递给它的属性渲染不同的文本。以下是该组件的代码:
// javascriptcn.com 代码示例 // Button.js import React from 'react'; function Button({ isLoading }) { return ( <button> {isLoading ? 'Loading...' : 'Submit'} </button> ); } export default Button;
我们将测试是否正确地为组件传递属性,以及是否正确地渲染了相应的文本。
// javascriptcn.com 代码示例 // Button.test.js import { shallow } from 'enzyme'; import Button from './Button'; describe('Button', () => { it('renders the submit button text', () => { const wrapper = shallow(<Button isLoading={false} />); expect(wrapper.find('button').text()).toBe('Submit'); }); it('renders the loading button text', () => { const wrapper = shallow(<Button isLoading={true} />); expect(wrapper.find('button').text()).toBe('Loading...'); }); });
上面的测试代码中,我们使用了 shallow
方法,该方法将组件渲染为浅层次的对象,不进行实际渲染或安装子组件。我们提供了两个测试用例,每个用例都创建了一个包含相应属性的组件,并断言渲染的文本是否正确。
测试受控组件
接下来,我们将测试一个受控组件。受控组件是指根据用户输入实时更新其值的组件。我们将测试一个名为 Input
的受控组件,该组件将用户输入限制为 5 个字符并显示输入计数。以下是该组件的代码:
// javascriptcn.com 代码示例 // Input.js import React, { useState } from 'react'; function Input() { const [value, setValue] = useState(''); const handleChange = (event) => { const newValue = event.target.value.slice(0, 5); setValue(newValue); }; return ( <div> <input value={value} onChange={handleChange} /> <div>{value.length} / 5</div> </div> ); } export default Input;
我们将测试是否正确地更新组件状态并计算输入计数。
// javascriptcn.com 代码示例 // Input.test.js import { shallow } from 'enzyme'; import Input from './Input'; describe('Input', () => { it('updates the value on input change', () => { const wrapper = shallow(<Input />); const input = wrapper.find('input'); input.simulate('change', { target: { value: 'hello' } }); expect(wrapper.state('value')).toBe('hello'); }); it('limits input to 5 characters', () => { const wrapper = shallow(<Input />); const input = wrapper.find('input'); input.simulate('change', { target: { value: 'hello world' } }); expect(wrapper.state('value')).toBe('hello'); }); it('displays value length', () => { const wrapper = shallow(<Input />); const count = wrapper.find('div').last(); expect(count.text()).toBe('0 / 5'); const input = wrapper.find('input'); input.simulate('change', { target: { value: 'hello' } }); expect(count.text()).toBe('5 / 5'); }); });
上面的测试代码中,我们使用了 shallow
方法,并使用了 simulate
方法模拟用户输入。我们断言组件状态是否正确地更新,并检查组件是否正确地限制了输入和显示了相应的计数。
测试异步组件
最后,我们将测试一个异步组件。异步组件通过网络检索数据并根据该数据进行渲染,因此需要使用 async
和 await
。我们将测试一个名为 User
的异步组件,该组件从 API 中检索用户数据并显示该数据。以下是该组件的代码:
// javascriptcn.com 代码示例 // User.js import React, { useState, useEffect } from 'react'; function User(props) { const { userId } = props; const [user, setUser] = useState(null); useEffect(() => { async function fetchData() { const response = await fetch(`https://api.example.com/users/${userId}`); const data = await response.json(); setUser(data); } fetchData(); }, [userId]); if (!user) { return <div>Loading...</div>; } return ( <div> <p>Name: {user.name}</p> <p>Email: {user.email}</p> </div> ); } export default User;
我们将测试是否正确地显示“正在加载”文本和正确的用户数据。
// javascriptcn.com 代码示例 // User.test.js import { mount } from 'enzyme'; import User from './User'; describe('User', () => { it('renders the loading state', () => { const wrapper = mount(<User userId={1} />); expect(wrapper.find('div').text()).toBe('Loading...'); }); it('renders the user data', async () => { const user = { id: 1, name: 'John Doe', email: 'john@example.com' }; jest.spyOn(window, 'fetch').mockImplementationOnce(() => Promise.resolve({ json: () => Promise.resolve(user), }) ); const wrapper = mount(<User userId={1} />); await Promise.resolve(); wrapper.update(); expect(wrapper.find('p').at(0).text()).toBe(`Name: ${user.name}`); expect(wrapper.find('p').at(1).text()).toBe(`Email: ${user.email}`); window.fetch.mockRestore(); }); });
上面的测试代码中,我们使用了 mount
方法,该方法将组件完全渲染,并使用 jest.spyOn
模拟了 API 数据。我们使用 async
和 await
等待异步操作完成,并使用 Promise.resolve
和 wrapper.update
更新组件。我们检查渲染的文本和正确的用户数据是否正确。
总结
通过使用 Enzyme 测试 React 应用程序,我们可以更好地保证代码的质量。无论我们是测试简单的组件还是复杂的受控和异步组件,我们都可以使用 Enzyme 来提高我们的测试效率和准确度。希望这个教程能帮助你更好地理解 Enzyme 的使用方式,并为你的 React 测试提供指导意义。
来源:JavaScript中文网 ,转载请注明来源 本文地址:https://www.javascriptcn.com/post/653a3a847d4982a6eb41e2a9