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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.01 00:50:23