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 元件庫)版本相符的 Adapter。例如,當您使用 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()
包含ReactTestUtils.act()
的api來進行包裝,因此您不需要手動進行包裝。
透過.act()
和斷言來觸發處理常式,常見模式是
const wrapper = mount(<SomeComponent />);
act(() => wrapper.prop('handler')());
wrapper.update();
expect(/* ... */);
我們無法在Enzyme中以.act()
包裝.prop()
(或.props()
)的結果,因為這會中斷傳回值的相等性。不過,您可以使用.invoke()
來簡化程式碼
const wrapper = mount(<SomeComponent />);
wrapper.invoke('handler')();
expect(/* ... */);
未來
貢獻
參閱貢獻指南
實際運用
使用enzyme
的組織和專案可以將自己列出在此。