【问题标题】:Unit testing error with act and useState, Making an API call in useEffectact 和 useState 的单元测试错误,在 useEffect 中进行 API 调用
【发布时间】:2021-03-08 01:12:38
【问题描述】:

我有一个反应功能组件,其中应用程序的 onload 我正在使用我已包装在 useEffect 中的 API 调用,当收到数据时我正在更新 useState 变量。 在使用 jest 和 react 测试库为以下组件编写单元测试用例时,我收到 act 错误和 useState 变量错误。 代码:

import React, { useState, useEffect } from "react";
import TextField from "@material-ui/core/TextField";
import Media from "./card";
import Alert from "@material-ui/lab/Alert";
import fetchData from "../API";
const Dashboard = () => {
  const [searchInput, setSearchInput] = useState(null);
  const [receipeNotFound, setReceipeNotFound] = useState(false);

  useEffect(() => {
    fetchData(
      `https://www.themealdb.com/api/json/v1/1/random.php`,
      randomReceipe
    );
  }, []);

  const randomReceipe = (result) => {
    result.meals ? setSearchInput(result.meals[0]) : setSearchInput(null);
  };

  const searchData = (value) => {
    if (value) {
      setSearchInput(null);
      setReceipeNotFound(false);
      fetchData(
        `https://www.themealdb.com/api/json/v1/1/search.php?s=${value}`,
        searchRecepie
      );
    } else {
      setSearchInput(null);
    }
  };

  const notFound = (status) => {
    setReceipeNotFound(status);
    setSearchInput(null);
  };

  const searchRecepie = (result) => {
    result.meals ? setSearchInput(result.meals[0]) : notFound(true);
  };

  return (
    <div>
      <TextField
        data-testid="searchInput"
        id="standard-basic"
        label="Search"
        onBlur={(event) => searchData(event.currentTarget.value)}
      />
      {receipeNotFound ? (
        <Alert data-testid="alert" severity="error">
          Receipe not found!
        </Alert>
      ) : null}
      {Boolean(searchInput) ? (
        <Media data-testid="mediaLoading" loading={false} data={searchInput} />
      ) : (
        <Media data-testid="Media" loading={true} data={{}} />
      )}
    </div>
  );
};

export default Dashboard;

测试:

import React from "react";
import Dashboard from "./dashboard";
import ReactDOM from "react-dom";
import {
  render,
  screen,
  act,
  waitFor,
  fireEvent,
} from "@testing-library/react";
import { randomMockWithOutVideo, randomMockWithVideo } from "./API.mock";
global.fetch = jest.fn();
let container;

describe("Card ", () => {
  test("Should renders data when API request is called with meals data", async (done) => {
    jest.spyOn(global, "fetch").mockResolvedValue({
      json: jest.fn().mockResolvedValue({ meals: [randomMockWithVideo] }),
    });
    const { getByTestId, container } = render(<Dashboard />);
    expect(global.fetch).toHaveBeenCalledTimes(1);
    expect(global.fetch).toHaveBeenCalledWith(
      `https://www.themealdb.com/api/json/v1/1/random.php`
    );
  });

  afterEach(() => {
    jest.restoreAllMocks();
  });
});

错误: 警告:测试中 Dashboard 的更新未包含在 act(...) 中。

  When testing, code that causes React state updates should be wrapped into act(...):

  act(() => {
    /* fire events that update state */
  });
  /* assert on the output */

19 |结果.餐? setSearchInput(result.meals[0]) : setSearchInput(null); | ^

【问题讨论】:

  • 第 19 行抛出的错误是什么?
  • 您使用的是什么版本的 RTL?

标签: reactjs jestjs react-testing-library


【解决方案1】:

此警告表明在您的组件被拆除后已对其进行了更新(通过 useState)。您可以在此处阅读 Kent C. Dodds 的完整解释:https://kentcdodds.com/blog/fix-the-not-wrapped-in-act-warning/

我会尝试这种语法来消除警告:

await act(() => {
  expect(global.fetch).toHaveBeenCalledTimes(1);
  expect(global.fetch).toHaveBeenCalledWith(`https://www.themealdb.com/api/json/v1/1/random.php`);
});

【讨论】:

    猜你喜欢
    • 2021-04-23
    • 2021-10-02
    • 2015-11-29
    • 2019-09-25
    • 2020-08-17
    • 2020-03-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多