Javascript 如何在React中使用rtl和jest测试异步函数

Javascript 如何在React中使用rtl和jest测试异步函数,javascript,reactjs,unit-testing,jestjs,react-testing-library,Javascript,Reactjs,Unit Testing,Jestjs,React Testing Library,我试图使用RTL和Jest在我的表单上测试我的异步提交函数,但在测试过程中遇到了一些错误。顺便说一句,这是我第一次测试我的代码,所以我对所有关于测试过程的事情都很困惑 这是我的错误: expect(jest.fn()).toHaveBeenCalled() Expected number of calls: >= 1 Received number of calls: 0 34 | 35 | fireEvent.submit(getByTestId('su

我试图使用RTL和Jest在我的表单上测试我的异步提交函数,但在测试过程中遇到了一些错误。顺便说一句,这是我第一次测试我的代码,所以我对所有关于测试过程的事情都很困惑

这是我的错误:

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

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

  34 |
  35 |         fireEvent.submit(getByTestId('submitBtn'))
> 36 |         expect(submitTodo).toHaveBeenCalled()
     |                            ^
  37 |     })
  38 | })
下面是我检查表单的代码

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

    fireEvent.submit(getByTestId('submitBtn'))
    expect(submitTodo).toHaveBeenCalled()
})
it('检查函数submitTodo',()=>{
const submitTodo=jest.fn();
const{getByTestId}=render();
const input=getByTestId('input');
更改(输入,{target:{value:'test'})
firevent.submit(getByTestId('submitBtn'))
expect(submitTodo).tohavebeincalled(提交)
})
这是我的表格和我的功能

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;
从'react'导入{useState};
从'firebase/firebaseConfig'导入{firestore};
从“firebase/firebaseConfig”导入firebase;
从“theme/main.module.scss”导入样式;
常量输入字段=()=>{
const[todo,setTodo]=useState(“”);
const submitTodo=异步(e)=>{
e、 预防默认值();
试一试{
等待firestore.collection('todo')。添加({
待办事项,
时间戳:firebase.firestore.FieldValue.serverTimestamp(),
});
}捕获(错误){
警报(错误);
}
setTodo(“”);
};
返回(
submitTodo(e)}
>
setTodo(e.target.value)}
/>
提交
);
};
导出默认输入字段;

此问题通常发生在正在测试的代码中存在某些异步操作时。因此,测试在异步方法返回之前完成

Jest有很多方法来测试文档中提到的异步函数。但是一个简单的方法是使用done回调

因此,您的测试代码如下

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

    expect.assertions(1);

    fireEvent.submit(getByTestId('submitBtn'))
    expect(submitTodo).toHaveBeenCalled()
    done();    
})
it('检查函数submitTodo',(完成)=>{
const submitTodo=jest.fn();
const{getByTestId}=render();
const input=getByTestId('input');
更改(输入,{target:{value:'test'})
期望.断言(1);
firevent.submit(getByTestId('submitBtn'))
expect(submitTodo).tohavebeincalled(提交)
完成();
})
done()回调确保jest将等待直到完成回调。expect.assertions还确保断言实际已做出,如果未做出断言,则断言将失败


更多详细信息和文档可以在

中找到,你是否应该调用按钮上的
单击
?Hi@HunterMcMillen,据我所知,如果我使用type=“submit”并再次添加额外的onClick,这将是多余的。使用RTL的最大一点是通过其API(即其道具和UI)与组件交互。您可能应该通过单击submit按钮来测试表单提交。
InputField
组件也不使用
submitTodo
道具,因此创建一个jest函数并传递它实际上不会产生任何效果。模拟
firestore
对象并断言它已被调用。您好@DrewReese,谢谢您的回复。如果你给我看一些关于模拟firestore对象的代码,可以吗?谢谢