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

React+TypeScript项目中Jest Mock Service方法失效问题排查咨询

React + TypeScript + Jest Mock失效问题解决方案

核心问题原因

  • 异步执行时序问题:组件中GetServiceData是异步方法,useEffect内的逻辑是微任务,你渲染组件后立刻执行断言/打印,此时异步逻辑还未执行完成,状态未更新,看起来像Mock未生效。
  • jest.mock写法错误:
    1. 导出结构不匹配:你的myservice.ts是默认导出包含GetServiceData的对象,Mock时没有对应default层级,也缺少__esModule标记适配ES模块导出规则。
    2. 返回值多嵌套了一层函数:mockReturnValue(() => Promise.resolve(mockData))会导致调用GetServiceData()返回的是函数而非Promise,异步逻辑无法正常执行。
    3. jest.mock调用必须放在测试文件所有import语句之前,Jest会自动将该调用提升到代码最顶部执行,如果放在import之后就会失效。

正确写法参考

方案1:使用jest.spyOn实现Mock

import React from 'react';
import TestRenderer from 'react-test-renderer';
import { act } from 'react-dom/test-utils';
import { MyComponent } from './mycomponent';
import myservice from '../services/myservice';
import { ServiceResponse } from '../services/serviceResponse';

const mockData: ServiceResponse[] = [
  { label: 'a', id: 'b'},
  { label: 'f', id: 'g'},
];

describe('mycomponent', () => {
  // 每个用例结束后清理所有Mock,避免互相影响
  afterEach(() => {
    jest.restoreAllMocks();
  });
  
  it('MyComponent returns data', async () => {
    // 直接用mockResolvedValue简化写法,不需要手动new Promise
    const getServiceDataSpy = jest.spyOn(myservice, 'GetServiceData').mockResolvedValue(mockData);

    let component: TestRenderer.ReactTestRenderer;
    // 用act包裹异步渲染,确保状态更新同步到测试环境
    await act(async () => {
      component = TestRenderer.create(<MyComponent />);
      // 等待微任务队列清空,触发useEffect内的异步逻辑执行完成
      await Promise.resolve();
    });

    // 此时已经可以正常拿到更新后的组件状态
    console.log(component.toJSON());
    // 示例断言:验证Mock方法被调用了1次
    expect(getServiceDataSpy).toHaveBeenCalledTimes(1);
  });
});

方案2:使用jest.mock实现全局Mock

// 必须放在所有import语句之前
jest.mock('../services/myservice', () => ({
  __esModule: true,
  default: {
    GetServiceData: jest.fn().mockResolvedValue([
      { label: 'a', id: 'b'},
      { label: 'f', id: 'g'},
    ])
  }
}));

import React from 'react';
import TestRenderer from 'react-test-renderer';
import { act } from 'react-dom/test-utils';
import { MyComponent } from './mycomponent';
import myservice from '../services/myservice';

describe('mycomponent', () => {
  it('MyComponent returns data', async () => {
    await act(async () => {
      TestRenderer.create(<MyComponent />);
      await Promise.resolve();
    });

    expect(myservice.GetServiceData).toHaveBeenCalledTimes(1);
  });
});

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.02 17:39:02