如果在 useEffect 之后没有发生任何事情,则进行反应测试

React test if something hasn't happened after useEffect

我正在使用 react-testing-libraryjest 来测试我的 API 是否在设置某个道具时未被调用。目前,测试会立即成功,而无需完成 useEffect() 调用。如何让测试等到 useEffect 完成,这样我才能确定 API 没有被调用?

代码:

const MyComponent = ({ dontCallApi }) => {
  React.useEffect(() => {
    const asyncFunction = async () => {
      if (dontCallApi) {
        return
      }

      await callApi()
    }
    asyncFunction
  }, [])

  return <h1>Hi!</h1>
}

it('should not call api when dontCallApi is set', async () => {
  const apiSpy = jest.spyOn(api, 'callApi')
  render(<MyComponent dontCallApi />)
  expect(apiSpy).not.toHaveBeenCalled()
})

在您的情况下,您可以监视 React.useEffect 并提供替代实现。 jest.spyOn(React, "useEffect").mockImplementation((f) => f()) 所以现在你不必再关心 useEffect 的处理了。

如果您还想以下降的方式测试 useEffect,您可以在自定义挂钩中提取逻辑并使用 testing library for hooksrenderHooks 函数来测试您的用例。

我会像这样测试您的组件:

import React from "react";
import { MyComponent } from "./Example";
import { render } from "@testing-library/react";
import { mocked } from "ts-jest/utils";
jest.mock("./api", () => ({
  callApi: jest.fn(),
}));
import api from "./api";
const mockApi = mocked(api);

jest.spyOn(React, "useEffect").mockImplementation((f) => f());
describe("MyComponet", () => {
  afterEach(() => {
    jest.clearAllMocks();
  });
  it("should not call api when dontCallApi is set", async () => {
    render(<MyComponent dontCallApi />);
    expect(mockApi.callApi).toHaveBeenCalledTimes(0);
  });

  it("should call api when is not set", async () => {
    render(<MyComponent />);
    expect(mockApi.callApi).toHaveBeenCalledTimes(1);
  });
});

编辑 03.07.2020

我最近发现可以在不模拟的情况下查询您想要的东西 useEffect。您可以简单地使用反应测试库的异步实用程序并获得以下内容:

import React from "react";

import { MyComponent } from "./TestComponent";
import { render, waitFor } from "@testing-library/react";
import { api } from "./api";

const callApiSpy = jest.spyOn(api, "callApi");

beforeEach(() => {
  callApiSpy.mockImplementation(() => Promise.resolve());
});
afterEach(() => {
  callApiSpy.mockClear();
});
describe("MyComponet", () => {
  afterEach(() => {
    jest.clearAllMocks();
  });
  it("should not call api when dontCallApi is set", async () => {
    render(<MyComponent dontCallApi />);
    await waitFor(() => expect(callApiSpy).toHaveBeenCalledTimes(0));
  });

  it("should call api when is not set", async () => {
    render(<MyComponent />);
    await waitFor(() => expect(callApiSpy).toHaveBeenCalledTimes(1));
  });
});

要了解更多信息,请查看 the async utilities docs