简体   繁体   English

单击处理程序模拟函数未调用

[英]Click handler mock function does not get called

Component I want to test: 我要测试的组件:

import React from 'react';
import { connect } from 'react-redux';
import { actionCreators as calculatorActionCreators } from './calculator';

class Pad extends React.Component {
  handleClick = () => {
    this.props.add(this.props.value);
  };
  render() {
    return (
      <div className="pad" onClick={this.handleClick}>
        {this.props.display}
      </div>
    );
  }
}

const mapStateToProps = state => ({});
const mapDispatchToProps = dispatch => ({
  add: val => dispatch(calculatorActionCreators.addExpression(val)),
});

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

The test: 考试:

import React from 'react';
import store from './store';
import Enzyme, { mount } from 'enzyme';
import Adapter from 'enzyme-adapter-react-16';

import Pad from './Pad';
it('adds calculation steps', () => {
  const mockAdd = jest.fn();
  const value = 1;
  const element = mount(
    <Pad
      store={store}
      value={value}
      add={mockAdd}
    />
  );
  const clickable = element.find('.pad');
  clickable.simulate('click');
  expect(mockAdd).toHaveBeenCalledWith(value);
});

I would expect that a simulated click on the .pad element invokes the handleClick , and thus this.props.add would get called. 我希望对.pad元素的模拟点击会调用handleClick ,因此this.props.add将被调用。 But when I run the test, I get this error: 但是当我运行测试时,出现以下错误:

Expected mock function to have been called with: [1] 预期的模拟函数已被调用:[1]

But it was not called 但这没有被称为

The app works when I test the app manually, so I guess there is something wrong with the way I try to test it. 当我手动测试应用程序时,该应用程序可以正常工作,因此我想我尝试对其进行测试的方式有问题。

EDIT: I found out how I can make the test pass: In Pad.js , also export the unwrapped component: 编辑:我发现了如何使测试通过:在Pad.js ,还导出了未包装的组件:

export class UnwrappedPad extends React.Component {
    ...
}
...
export default connect(mapStateToProps, mapDispatchToProps)(UnwrappedPad);

And in the test, use the unwrapped component instead of the connected one. 并且在测试中,使用展开的组件而不是连接的组件。

I still do not understand why it does not work when wrapping it in connect . 我仍然不明白为什么将它包装在connect时不起作用。

Seems like you are passing your handler to the container, not to the component. 好像您是将处理程序传递给容器,而不是传递给组件。 Whenever you simulate the click this is the method mapped to the props of your component which is called. 每当您模拟点击时,这就是映射到组件的props的方法,该方法称为。

So you have two possibilities. 因此,您有两种可能性。

1) Redux helps you to seperate presentation from behaviour so you can extract your presentational component and test it seperatly. 1)Redux帮助您将演示文稿与行为分开,因此您可以提取演示文稿组件并对其进行单独测试。 Your test will probably look something like: 您的测试可能看起来像:

it('adds calculation steps', () => {
  const mockAdd = jest.fn();
  const value = 1;
  const element = mount(<Pad value={value} add={mockAdd}/>);
  const clickable = element.find('.pad');

  clickable.simulate('click');

  expect(mockAdd).toHaveBeenCalledWith(value);
});

Your component like this: 您的组件是这样的:

export class Pad extends React.Component {

  handleClick = () => {
    this.props.add(this.props.value);
  };

  render() {
    return (
      <div className="pad" onClick={this.handleClick}>
        {this.props.display}
      </div>
    );
  }
}

2) If you really want to test the integration component and container then you might be able to use something like redux-mock-store . 2)如果您确实要测试集成组件和容器,则可以使用redux-mock-store之类的东西。 That would allow you to verify the action fired through the dispatcher. 这样您就可以验证通过调度程序触发的操作。 You test would probably look something like that: 您的测试可能看起来像这样:

it('adds calculation steps', () => {
  const mockStore = configureStore([])
  const store = mockStore({})
  const value = 1;
  const element = mount(
    <Provider store={store}>
      <Pad value={value}/>
    </Provider>
  );

  const clickable = element.find('.pad');

  clickable.simulate('click');

  expect(store.getActions()).toHaveBeenCalledWith([
    calculatorActionCreators.addExpression(val),
  ]);
});

Also the mapStateToProps method from redux get a 2nd argument which are the own porps of the container. 同样,来自redux的mapStateToProps方法也获得了第二个参数,它们是容器自己的容器。 I would then make explicite that the value is passed through. 然后,我将明确指出该值是通过的。

eg const mapStateToProps = (state, ownProps) => ({ value: ownProps.value}); 例如const mapStateToProps = (state, ownProps) => ({ value: ownProps.value});

Hope this helps! 希望这可以帮助!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM