NestJS测试中mockResolvedValueOnce参数类型never而非string问题
解决NestJS测试中Mock函数的TypeScript类型错误
测试NestJS应用时,搭建好测试代码结构后遇到类型错误:被Mock的函数本应返回string类型,但TypeScript提示参数必须为never类型。
报错信息
(method) jest.MockInstance<string, [expression: string]>.mockResolvedValueOnce(value: never): ((expression: string) => string) & jest.MockWithArgs<(expression: string) => string> & {} // 报错代码 service.getResult.mockResolvedValueOnce('2+2');
错误提示:Argument of type 'string' is not assignable to parameter of type 'never'.
完整测试代码
describe('CaclulatorController', () => { let controller: CalculatorController; let service: Pick<jest.MockedObject<CalculatorService>, 'getResult'>; let cache: Pick< jest.MockedObject<CacheService>, 'checkInCache' | 'setToCache' >; let history: Pick<jest.MockedObject<HistoryService>, 'create'>; beforeAll(async () => { const modRef = await Test.createTestingModule({ controllers: [CalculatorController], providers: [ { provide: CALCULATOR_SERVICE, useValue: { getResult: jest.fn(), }, }, { provide: CACHE_SERVICE, useValue: { checkInCache: jest.fn(), setToCache: jest.fn(), }, }, { provide: HISTORY_SERVICE, useValue: { create: jest.fn(), }, }, ], }).compile(); controller = modRef.get(CalculatorController); service = modRef.get(CALCULATOR_SERVICE); cache = modRef.get(CACHE_SERVICE); history = modRef.get(HISTORY_SERVICE); }); describe('getResult', () => { it('should get no response from the cache and perform a full caclulation', async () => { const dbResponse = { expression: '2+2+2*3', result: '10', _id: '63ecf3c0ca3cb4911dc5f013', }; cache.checkInCache.mockResolvedValueOnce(undefined); service.getResult.mockResolvedValueOnce('2+2+2*3'); //问题所在 history.create.mockResolvedValueOnce(); //同样问题,该函数应返回Promise cache.setToCache.mockResolvedValueOnce({ expression: '2+2+2*3', result: '10', _id: '63ecf3c0ca3cb4911dc5f013', }); await expect( controller.getResult({ expression: '2+2+2*3' }), ).resolves.toEqual(dbResponse); }); }); });
解决办法
1. 使用jest.mocked()包装服务实例
问题根源是TypeScript无法正确推断未包装的Mock实例类型。在获取服务实例时,用jest.mocked()包裹,确保类型正确关联原服务的方法签名:
// 修改beforeAll中的实例获取代码 service = jest.mocked(modRef.get(CALCULATOR_SERVICE)); cache = jest.mocked(modRef.get(CACHE_SERVICE)); history = jest.mocked(modRef.get(HISTORY_SERVICE));
这样TypeScript就能识别Mock函数的返回值和参数类型,不再提示never类型错误。
2. 显式指定Mock函数的类型
在创建Mock对象时,直接通过jest.fn的泛型参数指定返回值和参数类型:
// 修改CALCULATOR_SERVICE的provide配置 { provide: CALCULATOR_SERVICE, useValue: { getResult: jest.fn<string, [string]>(), // 第一个泛型是返回值类型,第二个是参数类型数组 }, }
同理,其他服务的Mock也可以用这种方式指定类型:
// CACHE_SERVICE示例 { provide: CACHE_SERVICE, useValue: { checkInCache: jest.fn<Promise<undefined | typeof dbResponse>, [string]>(), setToCache: jest.fn<Promise<typeof dbResponse>, [typeof dbResponse]>(), }, }
3. 修复history.create的Mock调用
如果history.create返回Promise<void>,需要显式传入undefined:
history.create.mockResolvedValueOnce(undefined);
如果返回特定类型,则传入对应类型的值即可。
内容的提问来源于stack exchange,提问作者tresor13
相关产品推荐
相关产品推荐

