React/Jest/Enzyme - 监视 changeHandler 在 .toHaveBeenCalledWith(event) 检查时失败

React/Jest/Enzyme - Spying on changeHandler fails on .toHaveBeenCalledWith(event) check

Input.tsx :

import React from "react";

export type InputProps = {
  name: string;
  label: string;
  value: any;
  onChange: React.FormEventHandler<HTMLInputElement>;
};

export const Input = ({ name, label, value, onChange }: InputProps) => {
  return (
    <div>
      <label htmlFor={name}>{label}</label>
      <input value={value} name={name} type="text" onChange={onChange} />
    </div>
  );
};

Input.test.tsx :

import React from "react";

import { mount } from "enzyme";
import { act } from "react-dom/test-utils";
import { Input, InputProps } from "./Input";

describe("Input tests", () => {
  test("renders without crashing", () => {
    const handleChange = jest.fn();

    const props: InputProps = {
      name: "login",
      label: "Your Login:",
      value: "",
      onChange: handleChange,
    };

    const wrapper = mount(<Input {...props} />);

    const mockEvent = {
      target: {
        value: "Administrator",
        name: "login",
      },
    } as React.ChangeEvent<HTMLInputElement>;

    act(() => {
      wrapper.find("input").simulate("change", mockEvent);
    });

    expect(handleChange).toHaveBeenCalledTimes(1);
    expect(handleChange).toHaveBeenCalledWith(mockEvent); // fails here
  });
});

带有 .toHaveBeenCalledWith(mockEvent) 的最后一行失败并显示以下消息:

expect(jest.fn()).toHaveBeenCalledWith(...expected)

- Expected
+ Received

+ SyntheticBaseEvent {
+   "_dispatchInstances": null,
+   "_dispatchListeners": null,
+   "_reactName": "onChange",
+   "_targetInst": FiberNode {
+     "_debugHookTypes": null,

Sample codesandbox here

我试过:

  1. onChange={onChange} 更改为 onChange={e => onChange(e)}
  2. target: {... 更改为 currentTarget: {...

但没有任何帮助。此时我不确定是因为我的输入是一个功能组件,还是版本有问题?任何帮助将不胜感激!

P.S。测试的目的是学习语法而不是实现有意义的覆盖。

simulate 将您的模拟事件对象与来自 ReactWrapperSyntheticEvent 对象合并(参见 the documentation of simulate),因此相等性测试将失败。相反,您可以这样做:

expect(handleChange).toHaveBeenCalledWith(expect.objectContaining(mockEvent));

这对 currentTarget 不起作用,因为 SyntheticEvent 已经有一个 属性 currentTarget: null,所以它也将是 null合并结果。对于 target 它确实有效。这是通过测试的sandbox

不过最好直接测试处理函数并远离 simulate,因为它有点 hacky 并且不能真正模拟事件。它甚至似乎已被弃用:https://github.com/enzymejs/enzyme/issues/2173