Enzyme使用指南

概述

Enzyme 是一款 react 组件测试工具。

Enzyme 基于 cheerio 实现虚拟 dom 的查找和遍历;而 cheerio 号称为服务器端的 jquery 实现。

Enzyme 本身不实现测试和断言库,你可以选择使用 Mocha/chai, Jasmine, Jest 等测试或断言库。

使用

  1. 安装 npm i –save-dev enzyme。
  2. 针对项目中使用的 react 版本,安装 enzyme-adapter-react-16, enzyme-adapter-react-15(15.5.0 版本起), enzyme-adapter-react-15.4(15.0.0 ~ 15.4.x), enzyme-adapter-react-14, enzyme-adapter-react-13 适配器。
  3. 配置 enzyme 以使用适配器。

    1
    2
    3
    4
    import Enzyme from 'enzyme';
    import Adapter from 'enzyme-adapter-react-16';

    Enzyme.configure({ adapter: new Adapter() });
  4. 编写测试用例。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    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.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);
    });
    });

api 手册

渲染模式

  1. 浅渲染:shallow(node[, options]) => ShallowWrapper。参数 node 为 ReactElement,options.context 传入组件的context,options.disableLifecycleMethods 生命周期方法是否有效。
  2. 完整渲染:mount(node[, options]) => ReactWrapper。options.context 传入组件的context,options.attachTo 生命周期方法是否有效。需要完整的 dom api,所以需要安装 jsdom 库。
  3. 静态渲染:render(node[, options]) => CheerioWrapper,渲染为 html,通过 cheerio 解析 html。

wrapper api

  1. .find(selector) => Wrapper
  2. .findWhere(predicate) => Wrapper
  3. .filter(selector) => Wrapper
  4. .filterWhere(predicate) => Wrapper
  5. .hostNodes() => Wrapper,事先存在于文档中 host 节点
  6. .contains(nodeOrNodes) => Boolean
  7. .containsMatchingElement(node) => Boolean
  8. .containsAllMatchingElements(nodes) => Boolean
  9. .containsAnyMatchingElements(nodes) => Boolean
  10. .equals(node) => Boolean
  11. .matchesElement(node) => Boolean
  12. .hasClass(className) => Boolean
  13. .is(selector) => Boolean
  14. .exists() => Boolean
  15. .isEmpty() => Boolean
  16. .isEmptyRender() => Boolean
  17. .not(selector) => Wrapper
  18. .children() => Wrapper
  19. .childAt(index) => Wrapper
  20. .parents() => Wrapper
  21. .parent() => Wrapper
  22. .closest(selector) => Wrapper
  23. .shallow([options]) => Wrapper,ShallowWrapper 独有
  24. .render() => CheerioWrapper
  25. .unmount() => Wrapper。ReactWrapper 独有 .mount() => Wrapper 方法
  26. .text() => String
  27. .html() => String
  28. .get(index) => ReactElement
  29. .getElement() => ReactElement。ReactWrapper 中为 .getNode() => ReactElement 方法
  30. .getElements() => Array。ReactWrapper 中为 .getNodes() => Array 方法。ReactWrapper 独有 .getDOMNode() => DOMComponent 方法。
  31. .at(index) => Wrapper
  32. .first() => Wrapper
  33. .last() => Wrapper
  34. .state([key]) => Any
  35. .context([key]) => Any
  36. .props() => Object
  37. .prop(key) => Any
  38. .key() => String
  39. .simulate(event[, data]) => Wrapper,模拟点击事件等
  40. .setState(nextState) => Wrapper
  41. .setProps(nextProps) => Wrapper
  42. .setContext(context) => Wrapper
  43. .instance() => ReactComponent
  44. .update() => Wrapper,调用 forceUpdate 方法强制更新组件实例。调用实例方法后,需要调用 .update 强制刷新 props。
  45. .debug() => String,.children 返回已渲染的节点,.children().debug() 返回渲染实际配置格式
  46. .type() => String|Function|null
  47. .name() => String
  48. .forEach(fn) => Wrapper
  49. .map(fn) => Array
  50. .reduce(fn[, initialValue]) => Any
  51. .reduceRight(fn[, initialValue]) => Any
  52. .slice([begin[, end]]) => Wrapper
  53. .tap(intercepter) => Self
  54. .some(selector) => Boolean
  55. .someWhere(predicate) => Boolean
  56. .every(selector) => Boolean
  57. .everyWhere(predicate) => Boolean
  58. .dive([options]) => Wrapper,ShallowWrapper 独有
  59. .ref(refName) => Wrapper,ReactWrapper 独有
  60. .detach() => void,ReactWrapper 独有