Enzyme 是 React 生态系统中一个流行的测试工具,用于轻松进行 React 组件的单元测试。在这篇文章中,我们将介绍如何使用 Enzyme 进行 React 项目的单元测试,并提供一些常见问题的解决方案。
安装 Enzyme
在使用 Enzyme 之前,需要先安装它。使用 npm 能够轻易地在你的项目中安装 Enzyme:
npm install --save-dev enzyme enzyme-adapter-react-16
然后,在测试代码中配置 Enzyme:
import Enzyme from 'enzyme';
import Adapter from 'enzyme-adapter-react-16';
Enzyme.configure({ adapter: new Adapter() });这个配置使 Enzyme 在测试 React 项目时能够正常地运行。
测试组件
有了 Enzyme 配置的帮助,下一步就是测试 React 组件了。我们将以一个简单的 Button 组件为例,介绍如何针对组件属性和用户操作进行测试。
// www.javascriptcn.com code example
import React from 'react';
import PropTypes from 'prop-types';
const Button = ({ onClick, text, disabled }) => (
<button disabled={disabled} onClick={onClick}>
{text}
</button>
);
Button.propTypes = {
onClick: PropTypes.func.isRequired,
text: PropTypes.string.isRequired,
disabled: PropTypes.bool,
};
export default Button;测试组件属性
让我们先来看看如何测试组件的属性是否正确。
// www.javascriptcn.com code example
import { mount } from 'enzyme';
import Button from './Button';
describe('<Button>', () => {
it('renders with text and onclick function', () => {
const mockOnClick = jest.fn();
const wrapper = mount(<Button onClick={mockOnClick} text="Test" />);
const button = wrapper.find('button');
expect(button.prop('disabled')).toEqual(false);
expect(button.text()).toEqual('Test');
button.simulate('click');
expect(mockOnClick).toHaveBeenCalledTimes(1);
});
});我们首先安装了 Enzyme,然后导入 <Button> 组件。在这个测试中,我们使用了 Mount API,因为测试需要实例化子组件并搜寻子组件。
我们声明了一个 mockOnClick 函数作为传递给 Button 组件的 onClick 属性,并将其传递给组件。 wrapper.find ('button') 在子组件中查找 button 元素。
接下来,我们测试了组件是否正确渲染了 text prop 和点击后 onClick 事件是否被调用。我们可以断言 button.prop 检查 disabled 标志,然后使用 simulate('click') 模拟用户点击 button 按钮,并断言 mockOnClick 被调用一次。
测试组件状态
比属性测试更高级的单元测试是测试 React 组件的状态。我们可以做到这一点通过 test 渲染组件,并模拟用户事件来触发其状态更改并验证其结果。
// www.javascriptcn.com code example
import { mount } from 'enzyme';
import Button from './Button';
describe('<Button>', () => {
it('sets the button to be disabled when disabled is true', () => {
const wrapper = mount(<Button disabled={true} onClick={() => {}} text="Test" />);
const button = wrapper.find('button');
expect(button.prop('disabled')).toEqual(true);
button.simulate('click');
expect(button.prop('disabled')).toEqual(true);
});
});在这个例子中,我们测试了组件的 disabled 属性,我们通过操作 button 以查询其属性是否受新状态更改的影响。 在这种情况下,我们期望按钮始终是不可用的,即使单击发生。
常见问题
Enzyme 如何处理 React 生命周期方法?
Enzyme 对于可以复制 React 生命周期方法的组件非常有用。 但是,对于内容动态生成的组件,这样的组件可能会抛出错误,因为无法确定节点何时可用于呈现。
例如,我们的 <Button> 组件可以通过开关属性使其渲染为 <a> 标签,而不是 <button> 元素。 这可能会导致 mount 方法返回一个无法满足交互的元素,因为如果渲染为一个 a 标签,则点击事件没有任何效果。
Enzyme 如何处理 CSS 模块?
如果你正在使用 CSS 模块并编写带有作为属性传递的类名的组件,有时 Enzyme 会找不到这些类名。 这是因为 Enzyme 无法解析已编译的类名。
解决方案:手动插入样式全局字符解决。
例如,如果你编写的组件需要在 CSS 模块化 y 中包含以下类:
.Text--bold {
font-weight: bold;
}你的测试可能会看起来像这样:
// www.javascriptcn.com code example
import { mount } from 'enzyme';
import Button from './Button';
describe('<Button>', () => {
it('sets the button to be bold when bold is true', () => {
const wrapper = mount(<Button bold={true} onClick={() => {}} text="Test" />);
const button = wrapper.find('button');
const className = button.prop('className');
expect(className.indexOf('Text--bold')).toBeGreaterThan(-1);
});
});在这个测试中, wrapper.find ('button') 返回 <button class =“ Text - bold”> </ button>, 然后我们断言该属性在类名中正确设置,以便最终断言要满足后代 className.indexOf('Text--bold')。
这样的测试可能会在使用 CSS 模块时变得很快笨拙。 如果你可以创建全局 CSS “命名空间”,那么你将能够轻松测试组件样式是否正确。 你可以重置这些样式并对组件使用这些命名空间 class。
来源:JavaScript中文网 ,转载请注明来源 https://www.javascriptcn.com/post/67d7afe3a941bf7134dc6f55