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

Enzyme mount测试Redux状态更新失败问题排查

问题分析与解决方案

你的问题核心在于异步操作的时序问题——测试代码在点击按钮后立刻执行断言,但此时moxios拦截的异步请求还未完成,Redux状态还没更新,组件也没有重新渲染,所以expect(wrapped.find("li").length).toBe(2)会失败。你看到的console.log输出其实是在测试跑完之后异步执行的,所以测试断言早于组件更新完成。

为什么会出现这种情况?

  1. 点击按钮触发fetchComments,这个action返回的是一个处于pending状态的Promise(由axios.get创建)。
  2. redux-promise中间件会等待这个Promise resolve后,才会分发真正的FETCH_COMMENTS action去更新Redux状态。
  3. 你的测试代码在点击后直接调用wrapped.update()并断言,这时候Promise还未resolve,状态还是初始的空数组,组件自然不会渲染<li>元素。

解决方案:等待异步操作完成

我们需要让测试等待moxios处理完请求、Redux状态更新、组件重新渲染后再执行断言。以下两种方式都可以实现:

方式一:使用moxios.wait()结合done回调

修改你的integration.test.js测试代码:

it("can fetch a list of comments and display them", (done) => {
  // 渲染整个应用
  const wrapped = mount(
    <Root>
      <CommentList />
    </Root>
  );

  // 找到按钮并模拟点击
  wrapped.find(".fetch-comments").simulate("click");

  // 等待moxios处理完所有待请求
  moxios.wait(() => {
    // 强制组件更新,确保状态变更反映到DOM上
    wrapped.update();
    // 此时断言就能拿到正确结果
    expect(wrapped.find("li").length).toBe(2);
    // 清理组件避免内存泄漏
    wrapped.unmount();
    // 通知Jest测试完成
    done();
  });
});

方式二:使用async/await语法

如果更习惯异步函数的写法,也可以这样修改:

it("can fetch a list of comments and display them", async () => {
  // 渲染整个应用
  const wrapped = mount(
    <Root>
      <CommentList />
    </Root>
  );

  // 找到按钮并模拟点击
  wrapped.find(".fetch-comments").simulate("click");
  
  // 等待moxios处理请求
  await moxios.wait();
  
  // 强制组件更新
  wrapped.update();

  // 执行断言
  expect(wrapped.find("li").length).toBe(2);
  
  // 清理组件
  wrapped.unmount();
});

补充说明

你的mock store测试能通过,是因为初始状态直接设置了comments数组,组件是同步渲染出<li>元素的,没有异步等待的问题。测试后记得调用wrapped.unmount()清理组件,避免内存泄漏。

内容的提问来源于stack exchange,提问作者Hylle

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.14 08:05:47