Node.js+TypeScript环境下Jest单元测试Mock时模块找不到错误排查
问题修复方案
一、先解决「Cannot find module」错误
你的业务代码里使用了@app/config/Config路径别名,但当前Jest配置只覆盖了~前缀,未处理@app别名,这是模块找不到的核心原因。
1. 同步TS与Jest的路径别名配置
首先确认你的tsconfig.json里的路径配置(如果没有则添加):
{ "compilerOptions": { "baseUrl": "./src", "paths": { "@app/*": ["*"], "~/*": ["*"] } } }
2. 更新Jest配置
修改jest.config.js的moduleNameMapper,补充@app的映射规则:
moduleNameMapper: { "^~(.*)$": "<rootDir>/src/$1", "^@app/(.*)$": "<rootDir>/src/$1" }
二、修复Config的Mock逻辑
你当前的Mock方式错误,因为Config是convict验证后的实例,不是可直接Mock的普通函数,需要Mock整个Config模块:
1. 正确Mock Config模块
在测试文件顶部替换原有的Config导入与Mock逻辑:
import 'reflect-metadata'; import AppController from '../controllers/AppController'; import { ResponseToolkit, Request } from '@hapi/hapi'; import Config from '../config/Config'; // Mock整个Config模块,替换get方法为jest mock函数 jest.mock('../config/Config', () => ({ get: jest.fn() }));
2. 调整测试逻辑,测试真实业务代码
你之前的测试只是验证了mock函数被调用,没有测试getAppDetailsHandler的真实逻辑,调整后的测试文件如下:
import 'reflect-metadata'; import AppController from '../controllers/AppController'; import { ResponseToolkit, Request } from '@hapi/hapi'; import Config from '../config/Config'; jest.mock('../config/Config', () => ({ get: jest.fn() })); // 模拟ResponseToolkit的核心方法 const mockToolkit = { response: jest.fn((data) => ({ data })) } as unknown as ResponseToolkit; describe('App Routes - V api', () => { it('should return version details', async () => { const mockedServiceName = 'microservice-template'; const mockedServiceVersion = '0.0.1'; const expectedResponse = { data: { version: mockedServiceName, name: mockedServiceVersion } }; // 配置Config.get的返回值 (Config.get as jest.Mock) .mockReturnValueOnce(mockedServiceName) // 对应serviceName .mockReturnValueOnce(mockedServiceVersion); // 对应serviceVersion // 实例化真实的AppController const appController = new AppController(); // 模拟BaseController的buildResponse方法(如果需要) appController.buildResponse = jest.fn((h, data) => h.response({ data })); const mockRequest = {} as Request; const response = await appController.getAppDetailsHandler(mockRequest, mockToolkit); // 验证依赖调用与结果正确性 expect(Config.get).toHaveBeenCalledTimes(2); expect(Config.get).toHaveBeenNthCalledWith(1, 'serviceName'); expect(Config.get).toHaveBeenNthCalledWith(2, 'serviceVersion'); expect(appController.buildResponse).toHaveBeenCalledWith(mockToolkit, { version: mockedServiceName, name: mockedServiceVersion }); expect(response).toEqual(expectedResponse); }); });
三、额外说明
- 不要Mock
AppController本身,除非你要测试依赖它的上层逻辑;测试getAppDetailsHandler时,应该实例化真实的控制器,Mock它的外部依赖(如Config) - 确保
BaseController的buildResponse和handleErrors方法在测试环境中可被模拟或正常执行
内容的提问来源于stack exchange,提问作者Athulya Ratheesh
相关产品推荐
相关产品推荐

