为何按控制台提示从react-test-renderer导入act会出现更多警告且测试失败
React组件快照测试act导入异常解决方案
问题根因
- 不同渲染器的act实现互相独立:正常规则是使用哪种渲染器渲染组件,就必须导入对应渲染器提供的act工具,你使用
react-test-renderer的TestRenderer渲染组件,理论上应该导入同包的act - 你遇到的是16.9.0之前版本React的已知缺陷:该版本区间的
react-test-renderer提供的act对异步场景支持不完整,处理Apollo MockProvider的异步状态更新、定时器逻辑时会漏捕更新,导致多重警告和测试失败 - 从
react-dom/test-utils导入的act能正常运行的原因是:旧版本react-dom的act实现是全局生效的,只要测试环境加载了react-dom,就能捕获所有React实例的更新,只是因为和你实际使用的TestRenderer渲染器不匹配,所以只会触发1条导入来源不匹配的警告
修复方案
临时适配方案
无需修改现有测试逻辑,在测试文件顶部添加警告过滤逻辑即可:
// 过滤act导入来源不匹配的警告 jest.spyOn(console, 'warn').mockImplementation((message) => { if (!message.includes('看起来你使用了错误的act()') && !message.includes('It looks like you are using the wrong act()')) { console.warn(message) } })
永久修复方案
- 确保
react、react-dom、react-test-renderer三个依赖的版本完全一致,且都升级到16.9.0及以上版本 - 将act的导入路径替换为
react-test-renderer,同时调整wait函数的异步act写法:
import TestRenderer, { act } from 'react-test-renderer'; export async function wait(ms = 0) { // 异步场景必须给act回调添加async标识 await act(async () => { await new Promise(resolve => setTimeout(resolve, ms)); }); }
- 可选优化:将TestRenderer.create的调用也包裹在act回调中,捕获组件初始渲染触发的异步更新,进一步减少警告:
it('matches its returned data snapshot', async () => { let wrapper; await act(async () => { wrapper = TestRenderer.create( <TestWrappingComponent mocks={mocks} children={<UpdateAgenda {...mockProps} />} /> ); }) await wait(); expect(wrapper.toJSON()).toMatchSnapshot(); });
内容的提问来源于stack exchange,提问作者Cookie
相关产品推荐
相关产品推荐

