如何模拟反应钩子内的函数

时间:2021-01-08 08:23:44

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

我试图测试表单提交。这是我的表单的样子。

const AccountForm = () => {
  const account = useAccount(null);
  const accountName = useInput("");
  const accountAmount = useInput(0);
  const [isLoading, setIsLoading] = useState(false);

  const onSubmit = async (event: FormEvent<HTMLFormElement>) => {
    event.preventDefault();
    setIsLoading(true);
    try {
      const acc: IAccount = {
        id: String(Date.now()),
        name: String(accountName.value),
        amount: Number(accountAmount.value),
        date: new Date().toLocaleDateString(),
      };
      await account.add(acc);
    } catch (error) {
      console.error(error);
    }
    setIsLoading(false);
  };

  return (
    <div data-testid="account-form-wrapper">
      <h2>Create new account</h2>
      <div>
        <form onSubmit={onSubmit}>
          <fieldset disabled={isLoading}>
            <label htmlFor="name">Name</label>
            <input
              type="text"
              name="name"
              id="name"
              autoComplete="off"
              value={accountName.value}
              onChange={accountName.onChange}
            />
          </fieldset>
          <fieldset disabled={isLoading}>
            <label htmlFor="amount">Amount</label>
            <input
              type="number"
              name="amount"
              id="amount"
              value={accountAmount.value}
              onChange={accountAmount.onChange}
            />
          </fieldset>
          <button
            type="submit"
            data-testid="submit-button"
            disabled={isLoading}
          >
            Create Account
          </button>
        </form>
      </div>
    </div>
  );
};

表单本身非常简单。它使用名为 useAccount 的自定义钩子返回 { value, add, set, edit }。 Returns 中的方法使 api 调用 firebase。我想知道如何使用 React 测试库测试(模拟)account.add

这是我尝试过的:我尝试像这样模拟 const mockAdd = jest.fn(hookWrapper.result.current.add); 。但它不会被调用!

import {
  toBeInTheDocument,
  toBeDisabled,
  toBeEnabled,
} from "@testing-library/jest-dom";
import { renderHook } from "@testing-library/react-hooks";
import { fireEvent, render, waitFor, act } from "@testing-library/react";
import AccountForm from "./form";
import useAccount from "../../hooks/useAccounts";

describe("./form.tsx", () => {
  test("renders <AccountForm />", async () => {
    const component = render(<AccountForm />);
    const hookWrapper = renderHook(useAccount);
    const submitBtn = component.getByText(/create account/i);
    const accountNameInput = component.getByLabelText(/name/i);
    const amountInput = component.getByLabelText(/amount/i);

    fireEvent.change(accountNameInput, { target: { value: "bank" } });
    fireEvent.change(amountInput, { target: { value: 200 } });

    expect(submitBtn).toBeInTheDocument();
    expect(submitBtn).toBeEnabled();

    const mockAdd = jest.fn(hookWrapper.result.current.add);

    waitFor(() => fireEvent.click(submitBtn));
    expect(mockAdd).toHaveBeenCalledTimes(1);
    expect(submitBtn).toBeDisabled();
  });
});

这是我的代码覆盖率的样子:

enter image description here

第 24 行是 catch 块,第 26 行是 setIsLoading。

0 个答案:

没有答案