【问题标题】:Mock function not being called using jest and testing library on react app没有在反应应用程序上使用 jest 和测试库调用模拟函数
【发布时间】:2021-10-18 05:39:26
【问题描述】:

我正在使用 jest 和测试库来测试表单。但是没有调用模拟函数。最后一行expect(mockOnSubmit).toHaveBeenCalled(); 总是失败。

这是我的测试代码:

App.test.js


import { render, fireEvent, cleanup } from "@testing-library/react";
import App from "./App";
import { act } from "react-dom/test-utils";

afterEach(cleanup);

test("email and password field are clear for submit", async () => {
  const mockOnSubmit = jest.fn();
  const { getByPlaceholderText, getByText } = render(
    <App onSubmit={mockOnSubmit} />
  );
  const emailNode = getByPlaceholderText(/email/i);
  const passwordNode = getByPlaceholderText(/password/i);

  const testEmail = "test@example.com";
  const testPassword = "123123";

  await act(async () => {
    fireEvent.change(emailNode, {
      target: { value: testEmail }
    });
    fireEvent.change(passwordNode, {
      target: { value: testPassword }
    });
  });

  expect(emailNode.value).toBe(testEmail);
  expect(passwordNode.value).toBe(testPassword);

  const submit = getByText(/submit/i);
  await act(async () => {
    fireEvent.click(submit);
  });
  expect(mockOnSubmit).toHaveBeenCalled();
});

App.js

import { useForm } from "react-hook-form";
import { Controller } from "react-hook-form";

export default function App({ onSubmit = (data) => console.log(data) }) {
  const { control, handleSubmit } = useForm();
  return (
    <form onSubmit={handleSubmit(onSubmit)}>
      <Controller
        name="email"
        control={control}
        defaultValue=""
        rules={{
          required: `Email is required.`,
          pattern: {
            value: /^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,4}$/i,
            message: "Invalid email address"
          }
        }}
        render={({ field }) => {
          return (
            <input
              placeholder="Email"
              type="text"
              key="email"
              name="email"
              id="email"
              {...field}
            />
          );
        }}
      />
      <Controller
        name="email"
        control={control}
        defaultValue=""
        rules={{
          required: `Password is required.`
        }}
        render={({ field }) => {
          return (
            <input
              placeholder="Password"
              type="text"
              key="password"
              name="password"
              id="password"
              {...field}
            />
          );
        }}
      />
      <input type="submit" value="submit" />
    </form>
  );
}

这个最小的实现也可以在 https://codesandbox.io/s/react-hook-form-testing-olo4i

旁注:没有react-hook-form 实现也可以正常工作。但是当我从react-hook-form 添加handleSubmit 时,它不再起作用了。这是@Florian Motteau 的working version,它通过绕过react-hook-form 来工作

【问题讨论】:

  • 请在问题中输入minimal reproducible example - App 是否真的处理 onSubmit 属性?
  • @jonrsharpe 出现在问题末尾的代码沙箱链接中。
  • 是的,但这不是问题。请注意How to Ask 中的指导。
  • 正如@jonrsharpe 所说,请将相关组件添加到问题中。但是顺便说一句,我认为问题在于控制器,要签出,使用简单的输入元素更改受控的“电子邮件”和“密码”组件,并尝试从“react-hook-forms”传递“注册”方法
  • 感谢您的建议,我添加了最小的可重现示例

标签: javascript reactjs jestjs react-testing-library react-hook-form


【解决方案1】:

您正在检查 onSubmit 道具是否已被调用,但在您的组件中,您在提交表单时并未调用此道具。所以你在测试中提供的模拟永远不会被调用。除此之外,在 App.js 中,onSubmit 属性被传递给handleSubmit (handleSubmit()) 的评估,而您必须传递对处理函数的引用(handleSubmit() =&gt; handleSubmit())。

解决你得到的这两个问题:

    // App.js
    export default function App({ onSubmit = (data) => console.log(data) }) {
      const { control, handleSubmit } = useForm();
      return (
        <form onSubmit={onSubmit}>
          <Box sx={{ mt: 2 }}>
            <EmailField label="Email" name="email" control={control} />
          </Box>
          <Box sx={{ mt: 2 }}>
            <PasswordField label="Password" name="password" control={control} />
          </Box>
          <Box sx={{ mt: 2 }}>
            <Button name="submit" type="submit" variant="contained">
              Submit
            </Button>
          </Box>
        </form>
      );
    }

我还建议您使用可视文本与 DOM 元素进行交互:

fireEvent.click(getByText("Submit"));

固定沙盒:https://codesandbox.io/s/react-hook-form-testing-forked-vs9ez?file=/src/App.js

最后,你不应该在 act() 中包装东西,react-testing-library 会为你做这件事,见https://kentcdodds.com/blog/fix-the-not-wrapped-in-act-warning

【讨论】:

  • 我需要将 onSubmit 添加为 &lt;form onSubmit={handleSubmit(onSubmit)}&gt; 这集成了 react-hook-library 中的 handleSubmit。只有这样验证才有效。直接应用onSubmit={onSubmit} 会绕过react-hook-form,所以这不适用于这种情况
  • 我明白了,但是当表单提交且没有错误时,您仍然需要调用使用 props 传递的处理程序。我不知道 react-hook-form 但不知何故你应该能够做到这一点,所以你的测试会通过。
  • 看来是这样,我会尝试在 react-hook-form 中找到一些东西来解决这个问题
猜你喜欢
  • 1970-01-01
  • 2021-08-31
  • 1970-01-01
  • 2022-01-06
  • 2019-12-09
  • 1970-01-01
  • 1970-01-01
  • 2020-07-22
  • 2021-05-20
相关资源
最近更新 更多