enzyme簡介——Airbnb的React測試框架

chezhe發表於2016-11-14

簡介

Enzyme是一個React的JavaScript測試工具,使React元件的輸出更加容易extrapolate
Enzyme的API和jQuery操作DOM一樣靈活易用。(因為其使用的是cheerio庫來解析虛擬DOM,而cheerio的目標則是做伺服器端的jQuery)
Enzyme相容大多數斷言庫和測試框架,如chaimochajasmine等。

安裝

npm i --save-dev enzyme

如果使用的是React 0.14React 15.x,請確保以下模組已經安裝

npm i --save-dev react-addons-test-utils
npm i --save-dev react-dom

基本用法

#### Shallow渲染

import React from `react`;
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.length(3);
  });

  it(`renders an `.icon-star``, () => {
    const wrapper = shallow(<MyComponent />);
    expect(wrapper.find(`.icon-star`)).to.have.length(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);
  });
});

#### 完整的DOM渲染

import React from `react`;
import sinon from `sinon`;
import { mount } from `enzyme`;

import MyComponent from `./MyComponent`;
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();
  });
});

#### 靜態渲染

import React from `react`;
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`).length).to.equal(3);
  });

  it(`renders the title`, () => {
    const wrapper = render(<Foo title="unique" />);
    expect(wrapper.text()).to.contain(`unique`);
  });
});

未來

完善CSS選擇器

現在還不支援分層(hierarchical)選擇器

完善事件模擬和對傳播的支援

對於 shallow rendering,事件模擬有限制,事件傳播也不支援,必須給出一個事件物件。

完善滑鼠和鍵盤的模擬

很多react控制元件涉及表單輸入框和複雜的滑鼠互動,使用Enzyme提供的事件API來模擬顯得笨重且不切實際。

相關文章