You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何移除React useFormContext组件测试时的DOM元素mock props警告

问题:React Testing Library测试使用useFormContext的组件时出现prop警告

运行测试时出现如下警告:

console.error
  Warning: React does not recognize the `mockResolvedValueOnce` prop on a DOM element.
  Warning: React does not recognize the `mockRejectedValueOnce` prop on a DOM element.

组件代码

const TextField: React.FC<OptionsField> = ({
  name,
  value,
  placeholder,
  label,
  required,
  type,
  disabled,
  fieldCaption = "",
  autoComplete = "off",
  customProps = {},
}) => {
  const methods = useFormContext();
  const [currentValue, setCurrentValue] = useState(value);
  const [status, setStatus] = useState("");

  useEffect(() => {
    methods.clearErrors(name);
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [status]);

  const validateText = (e: React.ChangeEvent<HTMLInputElement>) => {
    const text = e.target.value;
    text !== "" ? setStatus("writing") : setStatus("not writing");
  };

  const emptyFieldWhenRequired =
    methods.formState.errors[name] &&
    methods.formState.errors[name].type === "required";

  const valueNotChanged = currentValue === value;

  const errorStyle =
    emptyFieldWhenRequired && (currentValue === "" || valueNotChanged)
      ? "input-error"
      : "";

  const caption = fieldCaption && (
    <span className={fieldStyles["field-caption"]}>{fieldCaption}</span>
  );

  const requiredMessage = emptyFieldWhenRequired &&
    (currentValue === "" || valueNotChanged) && (
      <span className={styles["error-text"]}>Este campo es requerido</span>
    );

  return (
    <div className={styles.container}>
      <label>{label}</label>
      <input
        {...methods.register(name, { value, required })}
        className={`${styles.input} ${styles[errorStyle]}`}
        defaultValue={currentValue}
        type={type}
        placeholder={placeholder}
        disabled={disabled}
        autoComplete={autoComplete}
        onChange={(e) => {
          const value = e.target.value;
          setCurrentValue(value);
          methods.formState.errors[name] && validateText(e);
          methods.setValue(name, value);
        }}
        {...customProps}
      />
      {caption}
      {requiredMessage}
    </div>
  );
};

测试文件代码

import { render } from "@testing-library/react";
import TextField from "../TextField";
import { fireEvent, screen, waitFor } from "@testing-library/react";

const mockSubmit = jest.fn();

jest.mock("react-hook-form", () => ({
  ...jest.requireActual("react-hook-form"),
  useFormContext: () => ({
    register: () => jest.fn(),
    handleSubmit: () => mockSubmit,
    errors: () => jest.fn(),
    formState: { errors: {} },
    clearErrors: () => jest.fn(),
    setValue: () => jest.fn(),
  }),
}));

describe("TextField", () => {
  const setup = () => {
    return render(
      <TextField
        label="Mock TextField"
        required={true}
        placeholder="Mock Placeholder"
        type="text"
        value="mock value"
        name="mock name"
      />
    );
  };

  it("renders TextField without problem", () => {
    const view = setup();
    expect(view).toMatchSnapshot();
  });

  it("simulates change on input", async () => {
    setup();
    const input = screen.getByPlaceholderText("Mock Placeholder");
    fireEvent.change(input, {
      target: { value: "Mock something" },
    });
    await waitFor(() => {
      expect((input as HTMLInputElement).value).toBe("Mock something");
    });
  });
});

已尝试的方案:在setupTests.js和测试文件中mock console.error = jest.fn(),使用--silent参数,mock window.scrollTo解决了相关错误,但上述警告仍存在。


解决方案

问题根源

你在mock useFormContext时,让register返回了一个jest mock函数,但react-hook-form的register实际会返回包含input属性(如name、onChange、ref等)的对象。当你把这个mock函数展开到input元素上时,jest函数自带的mockResolvedValueOnce、mockRejectedValueOnce等方法会被当成DOM props传递,React不识别这些props,因此抛出警告。

修复方法

修改mock的register实现,让它返回一个空对象或者符合实际结构的对象,而非jest.fn():

基础修复(仅消除警告)

修改测试文件中的jest.mock部分:

jest.mock("react-hook-form", () => ({
  ...jest.requireActual("react-hook-form"),
  useFormContext: () => ({
    register: () => ({}), // 替换jest.fn()为空对象
    handleSubmit: () => mockSubmit,
    errors: () => jest.fn(),
    formState: { errors: {} },
    clearErrors: () => jest.fn(),
    setValue: () => jest.fn(),
  }),
}));

贴近实际场景的修复(若组件依赖register返回的属性)

如果你的组件需要register返回的特定属性(如onChange、ref),可以在返回对象中添加对应的mock:

register: () => ({
  name: "mock-name",
  onChange: jest.fn(),
  onBlur: jest.fn(),
  ref: jest.fn(),
})

备选方案:过滤特定警告

如果暂时不想修改mock逻辑,也可以在测试文件中添加警告过滤:

beforeAll(() => {
  const originalError = console.error;
  console.error = (...args) => {
    // 忽略目标警告
    if (/React does not recognize the `mockResolvedValueOnce` prop/.test(args[0])) {
      return;
    }
    // 保留其他错误输出
    originalError(...args);
  };
});

推荐优先使用第一种修复方式,从根源解决问题而非掩盖警告。


内容的提问来源于stack exchange,提问作者Mark Rivera

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.17 09:59:53