【问题标题】:How to test asynchronous function with rtl and jest in React如何在 React 中使用 rtl 和 jest 测试异步函数
【发布时间】:2021-05-22 02:56:58
【问题描述】:

我正在尝试使用 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()
})

这是我的表单和我的功能。

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;

【问题讨论】:

  • 你不应该在你的按钮上调用click吗?
  • 嗨@HunterMcMillen,据我所知,如果我有 type="submit" 并再次添加额外的 onClick,那将是多余的。
  • 使用 RTL 最大的一点是通过它的 API 与你的组件交互,即它的 props 和 UI。您可能应该通过单击提交按钮来测试表单提交。 InputField 组件也不使用 submitTodo 属性,因此创建一个 jest 函数并传递它实际上什么也没做。模拟 firestore 对象并断言它已被调用。
  • 嗨@DrewReese,感谢您的回复。如果您向我展示一些有关模拟 firestore 对象的代码,可以吗?谢谢

标签: javascript reactjs unit-testing jestjs react-testing-library


【解决方案1】:

当正在测试的代码中有一些异步操作时,通常会发生此问题。所以测试在异步方法返回之前完成。

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();    
})

done() 回调确保 jest 将等待直到完成回调。此外,expect.assertions 确保断言实际上是作出的,如果没有作出断言则失败。

更多细节和文档可以在official jest docs找到

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2022-11-10
    • 1970-01-01
    • 2020-08-04
    • 1970-01-01
    • 2019-07-22
    • 2020-10-27
    • 2018-10-31
    • 2016-09-15
    相关资源
    最近更新 更多