You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.10 19:14:54