在Jest + Enzyme中测试连接的容器方法

The*_*ice 3 unit-testing reactjs jestjs redux enzyme

我有一个这样的连接容器:

import React from 'react';
import PropTypes from 'prop-types';
import { bindActionCreators } from 'redux';
import { connect } from 'react-redux';
import { autobind } from 'core-decorators';

const propTypes = {
  data: PropTypes.object,
  userData: PropTypes.object,
};

class ConnectedContainer extends React.Component {
    @autobind
    doSomethingImportant() {
      ...
    }

  render() {
    ....
  }
}

ConnectedContainer.propTypes = propTypes;

const mapStateToProps = state => ({ data, userData });
const mapDispatchToProps = (dispatch) => {
  return { actions: bindActionCreators(actions, dispatch) };
};
export default connect(mapStateToProps, mapDispatchToProps)(ConnectedContainer);
Run Code Online (Sandbox Code Playgroud)

我要测试doSomethingImportant,所以我要进行如下测试:

import React from 'react';
import { shallow } from 'enzyme';
import ConnectedContainer from '.....'';
import configureStore from 'redux-mock-store';

const mockStore = configureStore();
const store = mockStore({ getState: () => null, dispatch: () => null, data: { data from fixture }, userData: { data from fixture } });
const container = (
  <ConnectedContainer
    store={store}
    actions={{}}
  />
);

describe('ConnectedContainer', () => {
  describe('doSomethingImportant', () => {
    it('returns something important', () => {
      const wrapper = shallow(container);
      expect(wrapper.instance().doSomethingImportant()).to.equal( ... some output here );
    });
  });
});
Run Code Online (Sandbox Code Playgroud)

而且无论我做什么,都会收到此错误:

TypeError: wrapper.instance(...). doSomethingImportant is not a function
Run Code Online (Sandbox Code Playgroud)

无法访问其实例方法的容器发生了什么情况?

sto*_*one 5

测试展开的组件

导出ConnectedContainer类本身,而不是包装版本。您要测试代码,而不是connect()函数。

您可以将默认导出保留为包装的组件,然后export在类定义前面添加单词:

export class ConnectedContainer extends React.Component { // Named export, for testing purposes only
    ...
}
Run Code Online (Sandbox Code Playgroud)

然后在您的测试中,import { ConnectedContainer } from '....' 使用shallow代替默认的输出。

命名约定

另外,命名您的组件ConnectedContainer也很令人困惑!它只有在使用connect函数包装后才可以连接。因此,当您导出ConnectedContainer(如我所建议的)时,您实际上是在导出未连接的组件类。(实际上是一个容器吗?这也很模糊。)

人们使用的一种命名约定是定义一个常量,该常量包含connect()的返回值,并命名 xxxContainer,如下所示:

export class IconView extends React.Component {  // Exported for testing
  // ... class implementation
}

function mapStateToProps(){...}
function mapDispatchToProps(){...}

const IconViewContainer = connect(mapStateToProps, mapDispatchToProps)(IconView);
export default IconViewContainer;  // Exported for use as a component in other views
Run Code Online (Sandbox Code Playgroud)