如何在componentDidMount中存根异步操作以使用Jest反应Redux连接的组件测试

时间:2019-05-14 23:11:55

标签: javascript reactjs redux jestjs

我有一个简单的连接组件,该组件在加载时会通过调用异步操作来构建用户详细信息,然后从状态中显示这些详细信息。

import PropTypes from 'prop-types';
import React from 'react';
import { connect } from 'react-redux';
import { loadUserDetails } from '../actions/user';

class ShowUserDetailsLite extends React.Component {
  componentDidMount() {
    this.props.loadUserDetails();
  }

  render() {
    const { userDetails } = this.props;

    const handleClickEdit = () => {
      history.push(editProfilePath());
    };

    return (
      <div>
        <div className="email">
          {userDetails.email_address}
        </div>
        <div className="name">
          {userDetails.first_name} {userDetails.last_name}
        </div>
      </div>
    );
  }
}

ShowUserDetailsLite.propTypes = {
  loadUserDetails: PropTypes.func.isRequired,
  userDetails: PropTypes.shape({}).isRequired,
};

const mapDispatchToProps = {
  loadUserDetails,
};

function mapStateToProps(state) {
  const userDetails = state.user.details;
  return { userDetails };
}

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

首先,我想测试我的组件从状态显示了正确的信息,因此我进行了以下测试。

import configureStore from 'redux-mock-store'
import { shallow } from 'enzyme';
import { expect } from 'chai';
import React from 'react'
import Provider from 'react-redux';
import ShowUserDetailsLite from '../../components/ShowUserDetailsLite'

describe('ShowUserDetailsLite component', () => {
  it('displays the current user', () => {
    const mockStore = configureStore();
    let store = mockStore({
      user: {
        details: {
          email_address: 'test@test.com',
          first_name: 'First',
          last_name: 'Last',
        }
      },
    });
    let wrapper = shallow(<ShowUserDetailsLite store={store} loadUserDetails={jest.fn()}/>).dive()
    expect(wrapper.find('.email').text()).to.eql('test@test.com')
  })
})

当我用componentDidMount函数注释掉运行此测试时,它运行良好,可以读取状态并显示正确的信息,但是当我运行包含componentDidMount函数的测试时,尝试进行测试调用该函数,然后出现以下错误:

 FAIL  app/tests/components/ShowUserDetailsLite.test.js
  ShowUserDetailsLite component
    ✕ displays the current user (32ms)

  ● ShowUserDetailsLite component › displays the current user

    ReferenceError: regeneratorRuntime is not defined

      16 |
      17 | export function loadUserDetails() {
    > 18 |   return async dispatch => {
         |   ^
      19 |     try {
      20 |       const res = await axios.get(`/${window.realm}/api/userDetails`);
      21 |       dispatch({ type: SET_USER_DETAILS, data: res.data });

在此阶段,我不关心测试loadUserDetails函数,因此我只想对它进行存根。我了解,要做到这一点,您只需要将函数作为属性传递即可,而我尝试通过传递一个笑话函数来做到这一点:

let wrapper = shallow(<ShowUserDetailsLite store={store} loadUserDetails={jest.fn()}/>).dive()

但是仍然出现错误。如何正确地对在componentdidmount中调用的异步操作存根进行连接的组件测试?

1 个答案:

答案 0 :(得分:0)

我可能来晚了,但最终我也因同样的问题而苦苦挣扎,在挖掘了两天之后,我发现:

由于使用Connect包装了组件,因此需要将残存的props函数传递给子组件

您可以在没有HOC连接的情况下导出组件

export ShowUserDetailsLite 

然后导入

import {ShowUserDetailsLite} from ...

现在您的组件变浅了,没有连接,您可以直接传递道具,例如用户和模拟的loadUserDetails

要更完整地回答原始问题:

如何对componentDidMount存根

当您mountshallow使用组件时,您将触发componentDidMount。

浅处

对于shallow渲染,您可以使用选项{disableLifecycleMethods:true}

 wrapper = shallow(
          <Stats {...props} />, {disableLifecycleMethods:true}
        )

带支架

如果您想使用mount进行渲染,则需要对componentDidMount进行如下操作:

jest.spyOn(YOUCOMPONENT.prototype, 'componentDidMount').mockImplementation();

然后安装组件

wrapper = mount(
      <Stats {...props} />
    )

现在,如果您想存根componentDidMount中调用的方法,则可以访问这些方法:

const spy = jest.spyOn(wrapper.instance(), 'myMethod').mockImplementation(() => {//do stuff})