反应组件中的网络请求后 Jest 函数无法触发

Jest function fails to fire after network request in react component

完整回购

https://github.com/brianbancroft/sample-testing-msw-sb-jest-rtl

使用模拟服务工作者 (msw) 响应网络请求,我有一个 React 登录组件。提交时它会发送一个网络请求,成功后它应该触发一个“handleClose”函数,它是组件的一个道具。

async function handleSubmit(event) {
    event.preventDefault();
    setLoading(true);

    const { username, password } = event.target.elements;

    try {
      const response = await fetch("/login", {
        method: "POST",
        mode: "cors",
        cache: "no-cache",
        credentials: "same-origin",
        headers: {
          "Content-Type": "application/json",
        },
        redirect: "follow",
        referrerPolicy: "no-referrer",
        body: JSON.stringify({
          username: username.value,
          password: password.value,
        }),
      });
      await response.json();

      if (response.status === 200) {
        props.handleClose();
      } else {
        setInvalidUsernamePassword(true);
        setLoading(false);
      }
    } catch (error) {
      alert("Error detected", error);
    }
  }

当我测试时,我验证函数 handleClose 被调用。


const setup = async () => {
  const handleClose = jest.fn();
  const utils = await render(<Primary handleClose={handleClose} />);
  const usernameField = screen.getByLabelText(/Username/);
  const passwordField = screen.getByLabelText(/Password/);
  const submitButton = screen.getByRole("button", {
    name: /Sign In/i,
  });

  return {
    usernameField,
    passwordField,
    submitButton,
    handleClose,
    ...utils,
  };
};

test("The handleClose function prop is triggered", async () => {
  const { usernameField, passwordField, submitButton, handleClose } =
    await setup();
  fireEvent.change(usernameField, { target: { value: faker.lorem.word() } });
  fireEvent.change(passwordField, { target: { value: faker.lorem.word() } });

  fireEvent.click(submitButton);

  expect(handleClose).toHaveBeenCalled();
});

这失败了


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

但是,当我在异步函数开始之前调用 prop 函数时,它通过了,这告诉我这不是我将 jest.fn() 传递到组件中的方式。

我调查了是否会抛出错误(它不会),而且我也知道 msw 正在按预期工作,并且网络请求以 200 响应,除非我发送密码值“badpassword”,用于在同一文件的另一个测试中模拟不正确的电子邮件或密码。

我还转换了函数以使用 promises。没有变化。

这就是 waitFor 实用方法在 React 测试库中的用途。

https://testing-library.com/docs/dom-testing-library/api-async/


  test("The handleClose function prop is triggered", async () => {
    const { usernameField, passwordField, submitButton, handleClose } =
      await setup();

    fireEvent.change(usernameField, { target: { value: faker.lorem.word() } });
    fireEvent.change(passwordField, { target: { value: faker.lorem.word() } });

    await fireEvent.click(submitButton);

    await waitFor(() => expect(handleClose).toHaveBeenCalled());
  });

现在测试通过了。