【问题标题】:How to test function that passed from mapDispatchToProps (React/Redux/Enzyme/Jest)如何测试从 mapDispatchToProps 传递的函数(React/Redux/Enzyme/Jest)
【发布时间】:2019-02-03 22:41:03
【问题描述】:

我想测试在模拟按钮单击时调用了从 mapDispatchToProps 传递的函数。

如何测试从 mapDispatchToProps 传递的函数被调用?

我试图通过 props 传递一个模拟函数,但它不起作用。任何帮助将不胜感激。

下面是我的假类代码和测试示例。

我的组件

// All required imports

class App extends React.Component<Props> {
  render() {
    const { onClick } = this.props;
    return (
      <>
        <h1>Form</h1>
        <input />
        <button onClick={() => onClick()} />
      </>
    );
  }
}

const mapStateToProps = (state) => {
  return {
    state
  };
};

const mapDispatchToProps = (dispatch) => {
  return {
    onClick: () => dispatch(actions.onClick())
  };
};

export default connect(mapStateToProps, mapDispatchToProps)(App);

我的测试文件

import { configure, mount } from 'enzyme';
import Adapter from 'enzyme-adapter-react-16/build/index';
import jsdom from 'jsdom';
import React from 'react';
import { Provider } from 'react-redux';
import configureMockStore from 'redux-mock-store';
import ConnectedApp, { App } from './App';

function setUpDomEnvironment() {
  const { JSDOM } = jsdom;
  const dom = new JSDOM('<!doctype html><html><body></body></html>', { url: 'http://localhost/' });
  const { window } = dom;
  global.window = window;
  global.document = window.document;
  global.navigator = {
    userAgent: 'node.js',
  };
  copyProps(window, global);
}

function copyProps(src, target) {
  const props = Object.getOwnPropertyNames(src)
    .filter(prop => typeof target[prop] === 'undefined')
    .map(prop => Object.getOwnPropertyDescriptor(src, prop));
  Object.defineProperties(target, props);
}

setUpDomEnvironment();

configure({ adapter: new Adapter() });


const mockStore = configureMockStore();

describe('App', () => {
  describe('When App connected to store', () => {
    describe('When button clicked', () => {
      it('should not crush after click on login button', () => {
      const onClick = jest.fn()
        const store = mockStore(initialStates[1]);
        const wrapper = mount(
          <Provider store={store}>
            <ConnectedApp />
          </Provider>);
        wrapper.find('button').simulate('click');
        ??? how to test that function passed from mapDispatchToProps was fired?
      });
    });
  });
});

【问题讨论】:

  • 你不能只检查状态对象以确保更改是从操作中进行的吗?

标签: reactjs redux jestjs enzyme


【解决方案1】:

我建议关注the approach described in the docs 并将连接的组件导出为default 导出以在应用程序中使用,并将组件本身导出为命名导出以进行测试。

对于export 上面的代码App 类并像这样测试点击:

import * as React from 'react';
import { shallow } from 'enzyme';
import { App } from './code';

describe('App', () => {

  it('should call props.onClick() when button is clicked', () => {
    const onClick = jest.fn();
    const wrapper = shallow(<App onClick={onClick} />);
    wrapper.find('button').simulate('click');
    expect(onClick).toHaveBeenCalledTimes(1);
  });

});

shallow 提供了测试组件本身所需的一切。 (shalloweven calls React lifecycle methods Enzyme v3)

正如您所发现的,要对组件进行完整渲染,需要模拟 redux 存储并将组件包装在 Provider 中。除了增加很多复杂性之外,这种方法最终还会在组件单元测试期间测试模拟存储和所有子组件。

我发现直接测试组件更有效,导出并直接测试mapStateToProps()mapDispatchToProps() 非常简单,因为它们应该是pure functions

上面代码中的mapDispatchToProps()可以这样测试:

describe('mapDispatchToProps', () => {
  it('should dispatch actions.onClick() when onClick() is called', () => {
    const dispatch = jest.fn();
    const props = mapDispatchToProps(dispatch);
    props.onClick();
    expect(dispatch).toHaveBeenCalledWith(actions.onClick());
  });
});

这种方法使得对组件进行单元测试非常简单,因为您可以直接传递组件 props,并且非常简单地测试组件将由传递给 @987654338 的纯函数 (or objects) 传递正确的 props @。

这可确保单元测试简单且有针对性。可以在 e2e 测试中测试 connect()redux 是否与组件及其所有子组件在完整 DOM 渲染中正常工作。

【讨论】:

    猜你喜欢
    • 2019-01-27
    • 1970-01-01
    • 1970-01-01
    • 2018-08-28
    • 2018-09-14
    • 2020-11-20
    • 2020-03-30
    • 2018-10-31
    • 2018-06-01
    相关资源
    最近更新 更多