开玩笑的预期模拟未调用(redux 组件)

Posted

技术标签:

【中文标题】开玩笑的预期模拟未调用(redux 组件)【英文标题】:Jest expected mock not called (redux component) 【发布时间】:2019-11-19 05:23:53 【问题描述】:

在 React 中,我正在测试子组件内的按钮单击会导致通过事件冒泡在父组件 (onDeleteClick) 中调用函数。 对于这个测试,我使用mount,因为浅层不允许我们在子组件中触发函数。

onDeleteClick,我试图检查它是否被调用的函数,是一个类属性,在这种情况下,它是一个箭头函数。

我正在模拟 onDeleteClick 函数,并在开始测试时通过 Redux Provider 将其传递到我的组件中。

我遇到的问题是,在测试结束时,当我执行检查以查看是否调用了模拟函数时,它返回 0。

expect(onDeleteClick.mock.calls.length).toBe(1);

如果我在onDeleteClick()中放了一个console.log,它会在测试过程中输出,所以我知道这个函数实际上是被调用的。

我对此进行了相当多的研究,到目前为止还没有任何工作。 一些建议是监视我的模拟函数,然后在包装器上调用 forceUpdate,但这并没有产生任何积极的结果。

为此,我使用JestEnzyme

参考代码:

父.js

    import  deleteAccount  from '../../actions/profileActions';
    import ChildComponent from '../common/ChildComponent';

    class ParentComponent extends Component 

      onDeleteClick = () => 
        console.log('onDeleteClick was executed during this test!')
        this.props.deleteAccount();
      

      render() 
        let dashboardContent;

        dashboardContent = (
           <div>
              <ChildComponent onDelete=this.onDeleteClick />
           </div>
        );

        return (
          <div>
             dashboardContent
          </div>
        );
      
    

    // propTypes and mapStateToProps removed from this post

    export default connect(
      mapStateToProps,
       deleteAccount 
    )(ParentComponent);

__tests__/ParentComponent.js


    import React from 'react';
    import  mount  from 'enzyme';
    import  BrowserRouter as Router  from 'react-router-dom';
    import  Provider  from 'react-redux';    
    import configureStore from 'redux-mock-store';
    import ParentComponent from '../ParentComponent';
    import thunk from "redux-thunk";    
    const mockStore = configureStore([thunk]);

    const deleteAccount = jest.fn();

    const props = 
      deleteAccount
    

    const randomTestState = 
    // some initial state, not important
    ;

    const randomTestStore = mockStore(randomTestState);

    describe('<ParentComponent />', () => 
      it(`mounts the ParentComponent component and, when ChildComponent sends onDelete, then deleteAccount function is called once`, () => 

        const wrapper = mount(
          <Provider store=randomTestStore props=props>
            <Router >
              <ParentComponent />
            </Router>
          </Provider>
        );

        // Here, I grab an element in ChildComponent and simulate a click using Enzyme, then the event bubbles up, and deleteAccount() is called in the parent component. 

        // the console.log we expect to see from onDeleteClick is logged to console.
        // the call does not seem to have registered though and the expect returns falsy

        expect(deleteAccount.mock.calls.length).toBe(1);
      )

    );

问题可能是我将组件包装在提供程序中吗? 我有预感,但我找不到任何在运行集成测试时使用 Provider 包装其组件的测试的具体示例

【问题讨论】:

【参考方案1】:

解决方案是我需要更改我的主 ParentComponent 文件

class ParentComponent extends Component 

到这里:

extend class ParentComponent extends Component 

然后在我的测试文件中,像这样导入组件:

import  ParentComponent  from '../ParentComponent'; // non-default export should be wrapped in braces

然后更新我的测试,以便我像这样分配包装器变量:

const wrapper = mount(<ParentComponent ...props />);

这样就可以通过测试了

expect(deleteAccount.mock.calls.length).toBe(1);

推荐here in the Redux docs

【讨论】:

以上是关于开玩笑的预期模拟未调用(redux 组件)的主要内容,如果未能解决你的问题,请参考以下文章

模拟 API 调用时未填充 Redux 存储

开玩笑地模拟 useDispatch 并在功能组件中使用该调度操作来测试参数

如何用玩笑模拟组件中使用的“嵌套”角度服务

reactjs - jest 快照测试嵌套的 redux “连接”组件

使用酶和主题测试样式化组件

不能用玩笑模拟模块,并测试函数调用