开玩笑预期已调用了模拟函数,但它被调用了零次(期望模拟.calls.length为1但为0)

时间:2019-07-09 15:41:12

标签: javascript reactjs jestjs enzyme redux-thunk

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

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

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

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

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

如果将console.log放在onDeleteClick()中,则它是在测试期间输出的,因此我知道实际上是在调用该函数。

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

为此,我将JestEnzyme一起使用。

参考代码:

Parent.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);
      })

    });

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

1 个答案:

答案 0 :(得分:0)

解决方案是我需要从更改我的主要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