act 和 useState 的单元测试错误,在 useEffect 中进行 API 调用
Posted
技术标签:
【中文标题】act 和 useState 的单元测试错误,在 useEffect 中进行 API 调用【英文标题】:Unit testing error with act and useState, Making an API call in useEffect 【发布时间】: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? 【参考方案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`);
);
【讨论】:
以上是关于act 和 useState 的单元测试错误,在 useEffect 中进行 API 调用的主要内容,如果未能解决你的问题,请参考以下文章
警告:测试中对 App 的更新未包含在酶和钩子中的 act(...) 中
Ruby on Rails:RSpec 和 Acts As Audited(在测试时禁用acts_as_audited?)