Enzyme
Enzyme 是一个用于 React 的 JavaScript 测试工具,它使测试 React 组件的输出变得更容易。您还可以操作、遍历,并在某些情况下模拟给定输出的运行时。
Enzyme 的 API 旨在通过模仿 jQuery 的 DOM 操作和遍历 API 来实现直观和灵活。
从 Enzyme 2.x 或 React < 16 升级
您是否要检查 Enzyme 是否与 React 16 兼容?您目前是否正在使用 Enzyme 2.x?太好了!查看我们的 迁移指南,以获取有关迁移到支持 React 16 的 Enzyme v3 的帮助。
安装
要开始使用 enzyme,您可以通过 npm 安装它。您需要安装 enzyme 以及与您使用的 react(或其他 UI 组件库)版本相对应的适配器。例如,如果您将 enzyme 与 React 16 一起使用,则可以运行
npm i --save-dev enzyme enzyme-adapter-react-16
每个适配器可能还有一些额外的对等依赖项,您也需要安装它们。例如,enzyme-adapter-react-16
对 react
和 react-dom
有对等依赖项。
目前,Enzyme 有适配器可以提供与 React 16.x
、React 15.x
、React 0.14.x
和 React 0.13.x
的兼容性。
以下适配器由 enzyme 官方提供,并具有以下与 React 的兼容性
Enzyme 适配器包 | React semver 兼容性 | ||
---|---|---|---|
enzyme-adapter-react-16 |
^16.4.0-0 |
||
enzyme-adapter-react-16.3 |
~16.3.0-0 |
||
enzyme-adapter-react-16.2 |
~16.2 |
||
enzyme-adapter-react-16.1 |
`~16.0.0-0 \ | \ | ~16.1` |
enzyme-adapter-react-15 |
^15.5.0 |
||
enzyme-adapter-react-15.4 |
15.0.0-0 - 15.4.x |
||
enzyme-adapter-react-14 |
^0.14.0 |
||
enzyme-adapter-react-13 |
^0.13.0 |
最后,您需要配置 enzyme 以使用您希望它使用的适配器。为此,您可以使用顶层的 configure(...)
API。
import Enzyme from 'enzyme';
import Adapter from 'enzyme-adapter-react-16';
Enzyme.configure({ adapter: new Adapter() });
第三方适配器
社区可以创建额外的(非官方)适配器,使 enzyme 可以与其他库一起使用。如果您创建了一个适配器,并且它没有包含在下面的列表中,请随时向此 README 发起 PR 并添加指向它的链接!已知的第三方适配器是
适配器包 | 用于库 | 状态 |
---|---|---|
enzyme-adapter-preact-pure |
preact |
(稳定) |
enzyme-adapter-inferno |
inferno |
(开发中) |
运行 Enzyme 测试
Enzyme 对您使用的测试运行器或断言库没有偏好,并且应该与所有主要的测试运行器和断言库兼容。Enzyme 的文档和示例使用 mocha 和 chai,但您应该能够将其推断到您选择的框架。
如果您有兴趣将 Enzyme 与自定义断言和便利函数一起使用来测试您的 React 组件,您可以考虑使用
chai-enzyme
与 Mocha/Chai 一起使用。jasmine-enzyme
与 Jasmine 一起使用。jest-enzyme
与 Jest 一起使用。should-enzyme
用于 should.js。expect-enzyme
用于 expect。
基本用法
浅渲染
import React from 'react';
import { expect } from 'chai';
import { shallow } from 'enzyme';
import sinon from 'sinon';
import MyComponent from './MyComponent';
import Foo from './Foo';
describe('<MyComponent />', () => {
it('renders three <Foo /> components', () => {
const wrapper = shallow(<MyComponent />);
expect(wrapper.find(Foo)).to.have.lengthOf(3);
});
it('renders an `.icon-star`', () => {
const wrapper = shallow(<MyComponent />);
expect(wrapper.find('.icon-star')).to.have.lengthOf(1);
});
it('renders children when passed in', () => {
const wrapper = shallow((
<MyComponent>
<div className="unique" />
</MyComponent>
));
expect(wrapper.contains(<div className="unique" />)).to.equal(true);
});
it('simulates click events', () => {
const onButtonClick = sinon.spy();
const wrapper = shallow(<Foo onButtonClick={onButtonClick} />);
wrapper.find('button').simulate('click');
expect(onButtonClick).to.have.property('callCount', 1);
});
});
阅读完整的 API 文档
完整 DOM 渲染
import React from 'react';
import sinon from 'sinon';
import { expect } from 'chai';
import { mount } from 'enzyme';
import Foo from './Foo';
describe('<Foo />', () => {
it('allows us to set props', () => {
const wrapper = mount(<Foo bar="baz" />);
expect(wrapper.props().bar).to.equal('baz');
wrapper.setProps({ bar: 'foo' });
expect(wrapper.props().bar).to.equal('foo');
});
it('simulates click events', () => {
const onButtonClick = sinon.spy();
const wrapper = mount((
<Foo onButtonClick={onButtonClick} />
));
wrapper.find('button').simulate('click');
expect(onButtonClick).to.have.property('callCount', 1);
});
it('calls componentDidMount', () => {
sinon.spy(Foo.prototype, 'componentDidMount');
const wrapper = mount(<Foo />);
expect(Foo.prototype.componentDidMount).to.have.property('callCount', 1);
Foo.prototype.componentDidMount.restore();
});
});
阅读完整的 API 文档
静态渲染的标记
import React from 'react';
import { expect } from 'chai';
import { render } from 'enzyme';
import Foo from './Foo';
describe('<Foo />', () => {
it('renders three `.foo-bar`s', () => {
const wrapper = render(<Foo />);
expect(wrapper.find('.foo-bar')).to.have.lengthOf(3);
});
it('renders the title', () => {
const wrapper = render(<Foo title="unique" />);
expect(wrapper.text()).to.contain('unique');
});
});
阅读完整的 API 文档
React Hooks 支持
Enzyme 支持 react hooks,在 .shallow()
中存在一些限制,这是由于 React 的浅渲染器中的上游问题。
ReactTestUtils.act()
包裹
如果您使用的是 React 16.8+ 和 .mount()
,Enzyme 会将包括 .simulate()
、.setProps()
、.setContext()
、.invoke()
在内的 API 与 ReactTestUtils.act()
进行包裹,因此您无需手动进行包裹。
使用 .act()
触发处理程序并进行断言的常见模式是
const wrapper = mount(<SomeComponent />);
act(() => wrapper.prop('handler')());
wrapper.update();
expect(/* ... */);
我们无法在 Enzyme 内部将 .prop()
(或 .props()
)的结果与 .act()
进行包裹,因为这会破坏返回值的相等性。但是,您可以使用 .invoke()
来简化代码
const wrapper = mount(<SomeComponent />);
wrapper.invoke('handler')();
expect(/* ... */);
未来
贡献
请参阅 贡献者指南
实际应用
使用 enzyme
的组织和项目可以将自己列在 这里。