Jest测试点击事件后状态未更新异常问题排查咨询
问题分析与解决方案
问题根源
你遇到的核心问题是测试未等待异步请求完成及组件状态更新:
- 点击触发
loadProduct后,Apollo的getProduct请求(即使是MockedProvider模拟的)的onCompleted回调是异步执行的,setProductState不会立刻更新组件状态。 - 测试中使用同步的
screen.getByAltText('B'),此时组件还未完成状态更新,因此拿到的是旧图片;而当测试报错时,Jest会有短暂等待,异步操作已完成,DOM已更新,所以报错信息里能看到新图片。
解决方案
修改测试代码,等待异步状态更新完成后再进行断言,常用两种方式:
方式1:使用waitFor包裹断言
test('Test 1', async () => { mockAllIsIntersecting(true); renderTest(() => ( <MockedApolloProvider mocks={[ getProductMock({ code: '7340266_F671' }), appSettingsSalesDocumentMock(), ]} > <ProductCard product={productMock} language="no" translated={translatedMock} /> </MockedApolloProvider> )); fireEvent.click(await screen.findByTitle('A')); // 等待组件更新,直到图片src符合预期 await waitFor(() => { const img = screen.getByAltText('B'); expect(img.getAttribute('src')).toEqual('C'); }); });
方式2:结合findBy与状态断言
由于图片的alt文本始终是B,可以直接等待图片的src属性变更:
test('Test 1', async () => { mockAllIsIntersecting(true); renderTest(() => ( <MockedApolloProvider mocks={[ getProductMock({ code: '7340266_F671' }), appSettingsSalesDocumentMock(), ]} > <ProductCard product={productMock} language="no" translated={translatedMock} /> </MockedApolloProvider> )); fireEvent.click(await screen.findByTitle('A')); // 直接等待图片的src变为预期值 const img = await screen.findByAltText('B', {}, { timeout: 1000 }); expect(img.getAttribute('src')).toEqual('C'); });
额外说明
- 组件中的
memo比较函数仅校验props的product.code,不影响内部useState触发的重新渲染,因此无需修改组件的memo逻辑。 waitFor会反复执行回调函数,直到断言通过或超时(默认1000ms),能确保等待所有异步操作完成。
内容的提问来源于stack exchange,提问作者Kim Vu
相关产品推荐
相关产品推荐

