每当我发出API请求并更新状态时,我都会不断在测试套件中获得Warning: An update to App inside a test was not wrapped in act(...).
。
我正在使用反应测试库。我还尝试使用ReactDOM测试工具,得到了相同的结果。我尝试的另一件事是将容器包装在act
中,仍然得到相同的结果。
请注意:我的应用程序正常运行,并且我的测试通过了。我只需要知道我在做错什么,或者是否是导致该错误出现的react-dom软件包中的错误。并且模拟控制台错误并将其静音是很不好的。
global.fetch = require('jest-fetch-mock');
it('should clear select content item', async () => {
fetch.mockResponseOnce(JSON.stringify({ results: data }));
const { container } = render(<App />);
const content = container.querySelector('.content');
await wait();
expect(content.querySelectorAll('.content--item').length).toBe(2);
});
这是钩子实现:
const [data, setData] = useState([]);
const [error, setError] = useState('');
const fetchInitData = async () => {
try {
const res = await fetch(API_URL);
const data = await res.json();
if (data.fault) {
setError('Rate limit Exceeded');
} else {
setData(data.results);
}
} catch(e) {
setError(e.message);
}
};
useEffect(() => {
fetchInitData();
}, [isEqual(data)]);
答案 0 :(得分:1)
这是一个已知问题,请在Github https://github.com/kentcdodds/react-testing-library/issues/281
中进行检查答案 1 :(得分:1)
对于像我一样在一年后迷失了方向的人,乔治已经提到的问题已得到解决,wait
已由waitFor
取代,如此处记录:>
https://testing-library.com/docs/dom-testing-library/api-async/
既然如此,我认为现在警告的解决方案应该是这样的:
import { render, waitFor } from '@testing-library/react';
// ...
it('should clear select content item', async () => {
fetch.mockResponseOnce(JSON.stringify({ results: data }));
const { container } = render(<App />);
const content = container.querySelector('.content');
await waitFor(() =>
expect(content.querySelectorAll('.content--item').length).toBe(2);
);
});
就我而言,我有一个App
组件在useEffect
钩子中异步加载数据,因此我在每个测试中都收到此警告,使用beforeEach
渲染{{ 1}}。这是针对我的情况的特定解决方案:
App
答案 2 :(得分:0)
要摆脱act()
警告,您需要确保您的诺言同步解决。您可以阅读here的操作方法。
摘要:
为此需要一些解决方案:
- 我们在全球范围内实现可实现的Promise承诺 “立即”承诺,例如promise
- 使用自定义babel设置(如此存储库中的那个)转换您的javascript
- 使用jest.runAllTimers();现在,这还将刷新Promise任务队列
答案 3 :(得分:-1)
我遇到了这个问题,放弃了使用wait和async,而是使用了jest faketimers等,因此您的代码应该是这样的。
global.fetch = require('jest-fetch-mock');
it('should clear select content item', /*async */ () => {
jest.useFakeTimers();
fetch.mockResponseOnce(JSON.stringify({ results: data }));
const { container } = render(<App />);
const content = container.querySelector('.content');
// await wait();
act(() => {
jest.runAllTimers();
});
expect(content.querySelectorAll('.content--item').length).toBe(2);
});