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

标签 reactjs jestjs react-testing-library

我正在使用 react-testing-libraryjest 来测试在设置某个 Prop 时我的 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,您可以在自定义 Hook 中提取逻辑并使用 testing library for hooks使用 renderHooks 函数来测试您的用例。

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

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 的情况下查询您想要的内容。您可以简单地使用 react 测试库的异步实用程序并获得以下内容:

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

关于reactjs - 如果在 useEffect 之后没有发生任何事情,则进行 react 测试,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62306109/

相关文章:

reactjs - redux sgas直接调用生成器方法可以吗

reactjs - React + Enzyme 错误 : Invariant Violation: dangerouslyRenderMarkup(. ..):无法在工作线程中渲染标记

reactjs - Jest 快照不匹配 - Windows 与 Unix/Linux 行尾

javascript - 如何在 Jest 中编写用于加载 Handlebars 模板文件的单元测试?

reactjs - 无法忽略带有 istanbul 的 React 类组件中的 block 忽略旁边以获得覆盖

reactjs - react 测试库渲染 VS ReactDOM.render

reactjs - 在 ReactJs 中为组件创建不同的移动布局

reactjs - 使用 React 中的 Axios 发出要表达的 http 请求在飞行前失败并出现 CORS 错误。在服务器上启用了 CORS 但仍然无法正常工作

javascript - 使用 jest 模拟其他模块中的函数依赖关系

reactjs - 如何获取renderHook的返回值