使用 jest 和 enzyme 进行测试时,在单击事件中不会调用模拟函数

Mock function is not called in click event while testing with jest and enzyme

我正在尝试测试一个连接到 redux 的 React 组件,即 Cart,但我无法进行以下测试。我想查看是否在按钮的单击处理程序中调用了一个操作(从 material-ui 包导入)。

动作通过 mapDispatchToProps 映射到道具。

const mapDispatchToProps = dispatch =>
  bindActionCreators(SelectItemGalleryActions, dispatch);

我也在用

import configureStore from 'redux-mock-store';

将模拟商店传递给我的测试组件。

已调用处理程序,但间谍未记录它已被调用。我已经尝试了我在这里或 github 上找到的大多数解决方案(浅、模拟、潜水、使用 jest.fn() 而不是 spy() ...);你有什么想法?我假设调用了对我尝试测试的模拟函数的不同引用。

首先我要传递一个模拟商店和一个动作

const props = {
  store: mockStore({ selectItemGallery: { cartItems: [{ name: 'one' }] } }),
  removeAllItemsFromCartAction: spy()
};
const wrapper = mount(<Cart {...props} />);

之后我搜索我的按钮并模拟点击它

const button = wrapper.find(Button).at(0);
button.prop('onClick')('test1');
button.prop('onClick')('test2');

当我 运行 测试时,点击有效。我从处理程序内部得到 console.log() 输出。

预期

expect(props.removeAllItemsFromCartAction.called).toBe(true);

然而它并没有被调用。

这是实际的处理程序

 <Button
    color="primary"
    onClick={x => {
      console.log(`onClick called on component with info ${x}`);
      removeAllItemsFromCartAction();
      console.log('removeAllItemsFromCartAction call is above me');
    }}>    
        {t('Clear All')}
 </Button>

控制台显示

欢迎任何提示或想法。谢谢。

版本:

"enzyme": "^3.8.0",
"enzyme-adapter-react-16": "^1.7.1",
"jest": "^23.6.0",
"sinon": "^7.2.2",
"react": "^16.8.2"

这些测试可能真的很挑剔,但我怀疑问题出在您设置间谍的方式上,因为根据您的控制台日志,该功能正在受到攻击。首先,我认为您实际上不需要间谍,只要 removeAllItemsFromCartAction() 实际上在您的组件道具上,您就可以使用传入的模拟函数。

const myMock = jest.fn();
const props = {
  store: mockStore({ selectItemGallery: { cartItems: [{ name: 'one' }] } }),
  removeAllItemsFromCartAction: myMock
};
const wrapper = mount(<Cart {...props} />);
const button = wrapper.find(Button).at(0);
button.simulate("click");
expect(myMock).toHaveBeenCalled();

你可能已经试过了,但这是我唯一的想法。

这似乎不是测试动作是否通过mapDispatchToProps映射到道具的正确方法 被调用了。

实际调用了模拟商店的调度,我们只需要验证它是否发送了正确的操作 (https://redux.js.org/recipes/writing-tests)。

正确的测试是:

  it('Should call the removeAllItemsFromCartAction', () => {
    const props = {
      store: mockStore({ selectItemGallery: { cartItems: [{ name: 'one' }] } })
    };
    const wrapper = mount(<Cart {...props} />);
    const button = wrapper.find(Button).at(0);
    button.prop('onClick')();
    console.log(props.store.getActions());
    expect(props.store.getActions()).toEqual([
      { type: 'REMOVE_ALL_ITEMS_FROM_CART' }
    ]);
  });