title: Jest - Mocking a function call within the handleSubmit of a form
body: <p>I am trying to write a test that mocks the calling of a function within the <code>handleSubmit</code> of a form, however, I am unable to show that the function has been called.</p>
  
  <p>The form is as follows:</p>
  
  <pre><code>import React, { Component } from 'react';
  import { connect } from 'react-redux';
  import { bindActionCreators } from 'redux';
  import signUp from '../../actions/users/sign_up';
  import PropTypes from 'prop-types';
  
  class Signup extends Component {
    constructor (props) {
      super(props);
  
      this.handleChange = this.handleChange.bind(this);
      this.handleSubmit = this.handleSubmit.bind(this);
      this.showError = this.showError.bind(this);
    }
  
    handleChange(event) {
      const target = event.target;
  
      this.setState({ [ target.name ]: target.value });
    }
  
    handleSubmit(event) {
      event.preventDefault();
      this.props.signUp(this.state);
    }
  
    showError(type) {
      if (this.state &amp;&amp; this.state.error &amp;&amp; this.state.error.data.errors[ type ]) {
        return this.state.error.data.errors[ type ][ 0 ];
      }
    }
  
    componentDidUpdate (prevProps, prevState) {
      const props = this.props;
  
      if (prevProps === props) {
        return;
      }
  
      this.setState({
        ...props,
      });
    }
  
    render () {
      return (
          &lt;div className='container-fluid'&gt;
              &lt;div className='row'&gt;
                  &lt;div className='col col-md-6 offset-md-3 col-sm-12 col-12'&gt;
                      &lt;div className='card'&gt;
                          &lt;div className='card-header'&gt;
                              &lt;h4&gt;Sign Up&lt;/h4&gt;
                          &lt;/div&gt;
                          &lt;div className='card-body'&gt;
                              &lt;form onSubmit={ this.handleSubmit } &gt;
                                  &lt;div className="form-row"&gt;
                                      &lt;div className="form-group col-md-12"&gt;
                                          &lt;label htmlFor="email"&gt;Email&lt;/label&gt;
                                          &lt;input
                          type="email"
                          name="email"
                          className={ `form-control ${ this.showError('email') ? 'is-invalid' : '' }` }
                          id="email"
                          placeholder="Email"
                          onChange={ this.handleChange }
                        /&gt;
                                          &lt;div className="invalid-feedback"&gt;
                                              { this.showError('email') }
                                          &lt;/div&gt;
                                      &lt;/div&gt;
                                  &lt;/div&gt;
                                  &lt;div className="form-row"&gt;
                                      &lt;div className="form-group col-md-12"&gt;
                                          &lt;label htmlFor="username"&gt;Username&lt;/label&gt;
                                          &lt;input
                          type="text"
                          name="username"
                          className={ `form-control ${ this.showError('username') ? 'is-invalid' : '' }` }
                          id="username"
                          placeholder="Username"
                          onChange={ this.handleChange }
                        /&gt;
                                          &lt;div className="invalid-feedback"&gt;
                                              { this.showError('username') }
                                          &lt;/div&gt;
                                      &lt;/div&gt;
                                  &lt;/div&gt;
                                  &lt;div className="form-row"&gt;
                                      &lt;div className="form-group col-md-12"&gt;
                                          &lt;label htmlFor="password"&gt;Password&lt;/label&gt;
                                          &lt;input
                            type="password"
                            name="password"
                            className={ `form-control ${ this.showError('password') ? 'is-invalid' : '' }` }
                            id="password"
                            placeholder="Password"
                            onChange={ this.handleChange }
                          /&gt;
                                          &lt;div className="invalid-feedback"&gt;
                                              { this.showError('password') }
                                          &lt;/div&gt;
                                      &lt;/div&gt;
                                      &lt;button type="submit" className="btn btn-primary"&gt;Sign Up&lt;/button&gt;
                                  &lt;/div&gt;
                              &lt;/form&gt;
                          &lt;/div&gt;
                      &lt;/div&gt;
                  &lt;/div&gt;
              &lt;/div&gt;
          &lt;/div&gt;
      )
    }
  }
  
  function mapStateToProps (state) {
    return {
      email: state.UsersReducer.email,
      username: state.UsersReducer.username,
      password: state.UsersReducer.password,
      error: state.UsersReducer.error,
    }
  }
  
  function mapDispatchToProps (dispatch) {
    return bindActionCreators({
      signUp: signUp,
    }, dispatch);
  }
  
  Signup.propTypes = {
    email: PropTypes.string,
    username: PropTypes.string,
    password: PropTypes.string,
    signUp: PropTypes.func.isRequired
  }
  
  export default connect(mapStateToProps, mapDispatchToProps)(Signup);
  </code></pre>
  
  <p>The <code>signUp</code> action looks like this:</p>
  
  <pre><code>import { SIGN_UP, SHOW_USER_ERRORS } from '../types';
  import axios from 'axios';
  import { API_ROOT,  setLocalStorageHeader } from './../../api-config';
  import { push } from 'react-router-redux';
  
  export default function signUp (params) {
    return dispatch =&gt; {
      axios.post(`${ API_ROOT }/auth.json`, params).then(res =&gt; {
        setLocalStorageHeader(res);
        dispatch(push('/profile'));
        dispatch(signUpAsync(res.data));
      }).catch(error =&gt; {
        dispatch({ type: SHOW_USER_ERRORS, payload: { error: error.response } });
      });
    }
  }
  
  function signUpAsync (data) {
    return {
      type: SIGN_UP,
      payload: data
    };
  }
  </code></pre>
  
  <p>I am trying to simulate the fact that the form will be submitted with the values obtained from the form inputs, which are in the form's state (<code>email</code>, <code>username</code> and <code>password</code>).</p>
  
  <p>The test I currently have is:</p>
  
  <pre><code>import React from 'react';
  import { shallow, mount } from 'enzyme';
  import configureStore from 'redux-mock-store';
  import { bindActionCreators } from 'redux';
  import thunk from 'redux-thunk';
  
  import Signup from '../../../components/users/signup';
  import UsersReducer from '../../../reducers/reducer_users';
  
  describe('&lt;Signup /&gt;', () =&gt; {
    describe('render()', () =&gt; {
      test('submits the form data',  async () =&gt; {
        const mockStore = configureStore([thunk]);
  
        const initialState = {
          UsersReducer: {
            email: '',
            username: '',
            password: '',
          },
        };
  
        const store = mockStore(initialState);
        const dispatchMock = jest.spyOn(store, 'dispatch');
  
        const signUp = jest.fn();
  
        const wrapper = shallow(&lt;Signup store={store} signUp={signUp} /&gt;);
        const component = wrapper.dive();
  
        component.find('#email').simulate(
          'change', {
            target: {
              name: 'email', value: 'foo@gmail.com'
            }
          }
        );
  
        component.find('#email').simulate(
          'change', {
            target: {
              name: 'username', value: 'foo'
            }
          }
        );
  
        component.find('#password').simulate(
          'change', {
            target: {
              name: 'password',
              value: '1234567',
            }
          }
        )
  
        component.find('form').simulate(
          'submit', {
            preventDefault() {}
          }
        )
  
        expect(dispatchMock).toHaveBeenCalled();
  
        expect(signUp).toHaveBeenCalledWith({
          email: 'foo@gmail.com',
          username: 'foo',
          password: '12345678'
        });
      });
    });
  });
  </code></pre>
  
  <p>But I keep getting the following error no matter what I try.</p>
  
  <pre><code>Expected mock function to have been called with:
    [{"email": "foo@gmail.com", "password": "12345678", "username": "foo"}]
  But it was not called.
  </code></pre>
  
  <p>I think it's due to the fact that <code>signUp</code> isn't being mocked properly in <code>shallow(&lt;Signup store={store} signUp={signUp} /&gt;)</code> because when I do <code>console.log(wrapper.props())</code> I get:</p>
  
  <pre><code>{
  ...
  signUp: [Function],
  ...
  }
  </code></pre>
  
  <p>rather than an indication that it's a mocked function:</p>
  
  <pre><code>{ [Function: mockConstructor]
     _isMockFunction: true,
  ...
  }
  </code></pre>
  
  <p>I know that the <code>signUp</code> action is being called by the <code>dispatch</code> of the test is passing. I can also see the <code>params</code> in the <code>signUp</code> action when I add a <code>console.log(params)</code> into it.</p>
  
  <p>Any assistance would be greatly appreciated.</p>