首页 > 解决方案 > 为在 Enzyme 中模拟 onClick 事件编写测试用例?

问题描述

HeaderBar.jsx我想在文件中编写测试用例HeaderBar.spec.jsx

首先,我想编写测试用例来检查我history.push()正在执行的调用,然后我想检查是否history.push()使用mockURL.

history.push()发现于onLogout()

这是HeaderBar.jsx

import React from 'react';
import { PropTypes } from 'prop-types';
import { bindActionCreators } from 'redux';
import { makeStyles } from '@material-ui/core/styles';
import AppBar from '@material-ui/core/AppBar';
import Toolbar from '@material-ui/core/Toolbar';
import Typography from '@material-ui/core/Typography';
import Button from '@material-ui/core/Button';
import IconButton from '@material-ui/core/IconButton';
import MenuIcon from '@material-ui/icons/Menu';
import { connect } from 'react-redux';
import { withTranslation } from 'react-i18next';
import { ROUTE_CONSTANTS, I18N_CONSTANTS } from '../../../../constants';
import { commonAction, sessionAction } from '../../../../redux/actions';

const useStyles = makeStyles(theme => ({
  root: {
    flexGrow: 1
  },
  menuButton: {
    marginRight: theme.spacing(2)
  },
  title: {
    flexGrow: 1
  }
}));

const HeaderBar = ({ history, t, actions }) => {
  const classes = useStyles();
  const onLogout = () => {
    history.push(ROUTE_CONSTANTS.MEMBER.LOGOUT);
    actions.logout();
  };
  // const onLogout = () => { throw new Error('Failed to run') };

  return (
    <div className={classes.root}>
      <AppBar position="static" color="default">
        <Toolbar>
          <IconButton edge="start" className={classes.menuButton} color="inherit" aria-label="menu">
            <MenuIcon />
          </IconButton>
          <Typography variant="h6" className={classes.title}>
            {t('headerBar.title')}
          </Typography>
          <Button color="inherit" onClick={onLogout}>
            {t('headerBar.logout')}
          </Button>
        </Toolbar>
      </AppBar>
    </div>
  );
};

HeaderBar.defaultProps = {
  t: () => {},
  history: {
    push: () => {}
  }
};

const mapStateToProps = state => {
  return {
    isLoading: state.common.loadingIndicator.isLoading
  };
};

const mapDispatchToProps = dispatch => {
  return {
    actions: bindActionCreators({ ...commonAction, ...sessionAction }, dispatch)
  };
};

HeaderBar.propTypes = {
  actions: PropTypes.shape({
    logout: PropTypes.func.isRequired
  }).isRequired,
  t: PropTypes.func,
  history: PropTypes.shape({
    push: PropTypes.func
  })
};

const component = connect(mapStateToProps, mapDispatchToProps)(HeaderBar);
export default withTranslation(I18N_CONSTANTS.NAMESPACE.APP)(component);

HeaderBar.spec.jsx

import React from 'react';
import { mount } from 'enzyme';
import { Provider } from 'react-redux';
import configureStore from '../../../../redux/store/configureStore';
import HeaderBar from './HeaderBar';

const setup = (props = {}) => {
  const store = configureStore();
  window.location.replace = jest.fn();
  const defaultProps = {
    isLoading: false,
    history: {
      replace: jest.fn(x => x)
    },
    ...props
  };
  return mount(
    <Provider store={store}>
      <HeaderBar {...defaultProps} />
    </Provider>
  );
};

describe('HeaderBar component', () => {
  it('should call translation 2 times', () => {
    const props = { t: jest.fn() };
    const wrapper = setup(props);

    const { t, isLoading } = wrapper.find('HeaderBar').props();

    expect(t).toHaveBeenCalledTimes(2);
    expect(isLoading).toBeFalsy();
  });

  it('should call history on onClick event', () => {
    const props = { history: { replace: jest.fn(x => x) }, onLogout: jest.fn(x => x) };
    const wrapper = setup(props);

    // console.log(wrapper.find('button').debug());
    wrapper.find('button').simulate('click');

    expect(props.history.replace).toHaveBeenCalledTimes(1);
  });

  it('should call history with mock URL', () => {
    const props = { history: { replace: jest.fn(x => x) } };
    const wrapper = setup(props);
    const mockURL = '/';

    wrapper
      .find('button')
      .at(0)
      .simulate('click');

    expect(props.history.replace).toHaveBeenCalledWith(mockURL);
  });
});

should call history on onClick event并且should call history with mock URL不适合我。

请帮我解决这个问题。

标签: reactjstestngenzyme

解决方案


  1. 您模拟 history.replace,但在您的组件中使用 history.push。
  2. 您将函数的实现模拟为 (x => x),但这些函数实际上不接收任何参数。
  3. 您的注销按钮真的是这个包装器的 DOM 中唯一的吗?也许添加一些ID?

推荐阅读