简体   繁体   中英

How to mock an asynchronous function using Jest

I've been trying to mock my submit function in jest but I always received this error:

expect(jest.fn()).toHaveBeenCalled()

Expected number of calls: >= 1
Received number of calls:    0

How can I solve this kind of error?

Here is my test file.

it('checks the function submitTodo', () => {
    const submitTodo = jest.fn();
    const { getByTestId } = render(<InputField />);
    const input = getByTestId('input');
    fireEvent.change(input, { target: { value: 'test' } })

    fireEvent.submit(getByTestId('form'))
    expect(submitTodo).toHaveBeenCalled()
})

and here is my functional component where I'm calling my async function.

import { useState } from 'react';
import { firestore } from 'firebase/firebaseConfig';
import firebase from 'firebase/firebaseConfig';
import styles from 'theme/main.module.scss';

const InputField = () => {
  const [todo, setTodo] = useState('');

  const submitTodo = async (e) => {
    e.preventDefault();
    try {
      await firestore.collection('todo').add({
        todo,
        timestamp: firebase.firestore.FieldValue.serverTimestamp(),
      });
    } catch (error) {
      alert(error);
    }
    setTodo('');
  };
  return (
    <form
      data-testid='form'
      className={styles.inputFieldContainer}
      onSubmit={(e) => submitTodo(e)}
    >
      <input
        data-testid='input'
        className={styles.inputFieldContainer__input}
        placeholder='Please enter a todo.'
        required
        value={todo}
        onChange={(e) => setTodo(e.target.value)}
      />
      <button
        data-testid='submitBtn'
        className={styles.inputFieldContainer__btn}
        type='submit'
      >
        Submit
      </button>
    </form>
  );
};

export default InputField;

submitTodo is an inner function of InputField . you can't mock it directly using jest.fn(). If you just want to test whether the submitTodo function is called then you can do this.

it('checks the function submitTodo', () => {
    const submitTodoForTest = jest.fn();
    const { getByTestId } = render(<InputField submitTodoForTest={submitTodoForTest} />);
    const input = getByTestId('input');
    fireEvent.change(input, { target: { value: 'test' } })

    fireEvent.submit(getByTestId('form'))
    expect(submitTodoForTest).toHaveBeenCalled()
})

// In your component
  const InputField = ({submitTodoForTest = null}) => {
  const [todo, setTodo] = useState('');

  const submitTodo = async (e) => {
  submitTodoForTest && submitTodoForTest();
    e.preventDefault();
    try {
      await firestore.collection('todo').add({
        todo,
        timestamp: firebase.firestore.FieldValue.serverTimestamp(),
      });
    } catch (error) {
      alert(error);
    }
    setTodo('');
  };
  return (
    ....
  );
};

But if you need to test whether the fireStore is called, then you need to mock the fireStore as well.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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