React+TypeScript项目中Jest Mock Service方法失效问题排查咨询
React + TypeScript + Jest Mock失效问题解决方案
核心问题原因
- 异步执行时序问题:组件中
GetServiceData是异步方法,useEffect内的逻辑是微任务,你渲染组件后立刻执行断言/打印,此时异步逻辑还未执行完成,状态未更新,看起来像Mock未生效。 jest.mock写法错误:- 导出结构不匹配:你的
myservice.ts是默认导出包含GetServiceData的对象,Mock时没有对应default层级,也缺少__esModule标记适配ES模块导出规则。 - 返回值多嵌套了一层函数:
mockReturnValue(() => Promise.resolve(mockData))会导致调用GetServiceData()返回的是函数而非Promise,异步逻辑无法正常执行。 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
相关产品推荐
相关产品推荐

