reactjs - 警告:测试中对 App 的更新未包含在酶和钩子中的 act(...) 中
问题描述
我已经写了这个组件。它使用钩子和状态获取数据。获取后,加载状态将更改为 false 并显示侧边栏。
我遇到了 Jest 和 Enzyme 的问题,因为它确实在我的单元测试中对 Act 发出了警告。一旦我将行为添加到我的笑话和酶中,测试就失败了!
// @flow
import React, { useEffect, useState } from 'react';
import Sidebar from '../components/Sidebar';
import fetchData from '../apiWrappers/fetchData';
const App = () => {
const [data, setData] = useState([]);
const [loading, setLoading] = useState(true);
useEffect(() => {
const getData = async () => {
try {
const newData = await fetchData();
setData(newData);
setLoading(false);
}
catch (e) {
setLoading(false);
}
};
getData();
// eslint-disable-next-line
}, []);
return (
<>
{!loading
? <Sidebar />
: <span>Loading List</span>}
</>
);
};
export default App;
而且,我添加了一个这样的测试,效果很好。
import React from 'react';
import { mount } from 'enzyme';
import fetchData from '../apiWrappers/fetchData';
import data from '../data/data.json';
import App from './App';
jest.mock('../apiWrappers/fetchData');
const getData = Promise.resolve(data);
fetchData.mockReturnValue(getData);
describe('<App/> Rendering using enzyme', () => {
beforeEach(() => {
fetchData.mockClear();
});
test('After loading', async () => {
const wrapper = mount(<App />);
expect(wrapper.find('span').at(0).text()).toEqual('Loading List');
const d = await fetchData();
expect(d).toHaveLength(data.length);
wrapper.update();
expect(wrapper.find('span').exists()).toEqual(false);
expect(wrapper.html()).toMatchSnapshot();
});
});
所以,我收到一个警告:
Warning: An update to App inside a test was not wrapped in act(...).
When testing, code that causes React state updates should be wrapped into act(...):
act(() => {
/* fire events that update state */
});
我确实使用 { act } react-dom/test-utils 解决了这样的警告。
import React from 'react';
import { act } from 'react-dom/test-utils';
import { mount } from 'enzyme';
import fetchData from '../apiWrappers/fetchData';
import data from '../data/data.json';
import App from './App';
jest.mock('../apiWrappers/fetchData');
const getData = Promise.resolve(data);
fetchData.mockReturnValue(getData);
describe('<App/> Rendering using enzyme', () => {
beforeEach(() => {
fetchData.mockClear();
});
test('After loading', async () => {
await act(async () => {
const wrapper = mount(<App />);
expect(wrapper.find('span').at(0).text()).toEqual('Loading List');
const d = await fetchData();
expect(d).toHaveLength(data.length);
wrapper.update();
expect(wrapper.find('span').exists()).toEqual(false);
expect(wrapper.html()).toMatchSnapshot();
});
});
});
但是,然后我的测试失败了。
<App/> Rendering using enzyme › After loading
expect(received).toEqual(expected) // deep equality
Expected: false
Received: true
35 |
36 | wrapper.update();
> 37 | expect(wrapper.find('span').exists()).toEqual(false);
有人知道为什么会失败吗?谢谢!
"react": "16.13.1",
"enzyme": "^3.11.0",
"enzyme-adapter-react-16": "^1.15.3",
解决方案
这个问题一点也不新鲜。你可以在这里阅读完整的讨论:https ://github.com/enzymejs/enzyme/issues/2073 。
总而言之,目前为了修复act
警告,您必须稍等片刻才能更新包装器,如下所示:
const waitForComponentToPaint = async (wrapper) => {
await act(async () => {
await new Promise(resolve => setTimeout(resolve));
wrapper.update();
});
};
test('After loading', async () => {
const wrapper = mount(<App />);
expect(wrapper.find('span').at(0).text()).toEqual('Loading List');
// before the state updated
await waitForComponentToPaint(wrapper);
// after the state updated
expect(wrapper.find('span').exists()).toEqual(false);
expect(wrapper.html()).toMatchSnapshot();
});
推荐阅读
- web - 从网络聊天控件调用 Skype for Business
- corda - AWS 上的 Corda 分布式
- wpf - 当 TreeViewItem 包含带有 DropShadowEffect 的边框时,如何应用 TreeView 突出显示颜色?
- c++ - 如何将 QVariant 转换为 QDomNode
- angular - 未找到 e 的组件工厂。你把它添加到@NgModule.entryComponents 了吗?
- lisp - #1# 不是符号或 lambda 表达式
- c++ - c++ 使用类成员作为模板参数
- python - 预期的 str、bytes 或 os.PathLike 对象,而不是 NoneType
- python-3.x - 通过求解集查找根
- c# - 无法返回 XLWorkbook 中工作表中单元格的值