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

如何用Jest对类型安全的NestFactory.create方法进行部分Mock

问题

我有一个TypeScript应用,正在使用Jest来Mock NestFactory类的create方法。通常,create方法会返回包含20余个方法/属性的INestApplication实例,但我仅关注其中的listen方法。我希望Mock create方法使其返回带有Mock化listen的对象以开展测试,当前实现会触发类型错误,且不想通过转换为any类型破坏类型安全,请问如何实现类型安全的Mock?

代码示例:

import { NestFactory } from '@nestjs/core';

// Jest自动Mock
jest.mock('@nestjs/core');

// 获取带类型安全的Mocked NestFactory
const mockedNestFactory = jest.mocked(NestFactory);

test('', () => {
  // 希望create返回的Mock化listen函数
  const mockedListen = jest.fn();

  // 此处触发类型错误,因返回对象仅含listen,缺少INestApplication的其他成员
  mockedNestFactory.create.mockResolvedValue({
    listen: mockedListen,
  });
});

解决方案

方案1:使用Partial类型结合安全断言

导入INestApplication后,用Partial<INestApplication>定义仅包含listen的mock对象,再通过类型断言转换为INestApplication。这种方式既保留类型检查,又无需实现所有未用到的属性。

import { NestFactory, INestApplication } from '@nestjs/core';

jest.mock('@nestjs/core');

const mockedNestFactory = jest.mocked(NestFactory);

test('测试NestFactory创建应用并监听', async () => {
  const mockedListen = jest.fn().mockResolvedValue(true);
  
  // 定义仅包含listen的Partial对象
  const mockApp: Partial<INestApplication> = {
    listen: mockedListen,
  };

  // 安全断言为INestApplication(测试中不会访问其他属性)
  mockedNestFactory.create.mockResolvedValue(mockApp as INestApplication);

  // 执行测试逻辑
  const app = await NestFactory.create();
  await app.listen(3000);
  
  expect(mockedListen).toHaveBeenCalledWith(3000);
});

方案2:用Pick提取所需类型

通过Pick<INestApplication, 'listen'>从原类型中仅提取listen方法的类型,确保mock对象的类型与原类型完全匹配,再进行断言。

import { NestFactory, INestApplication } from '@nestjs/core';

jest.mock('@nestjs/core');

const mockedNestFactory = jest.mocked(NestFactory);

// 仅提取需要用到的listen方法类型
type MockedNestApp = Pick<INestApplication, 'listen'>;

test('测试NestFactory的listen调用', async () => {
  const mockedListen = jest.fn().mockResolvedValue(true);
  
  const mockApp: MockedNestApp = {
    listen: mockedListen,
  };

  mockedNestFactory.create.mockResolvedValue(mockApp as INestApplication);

  // 执行测试逻辑
  await NestFactory.create().then(app => app.listen(3000));
  
  expect(mockedListen).toHaveBeenCalled();
});

方案3:自定义mock实现并占位未用方法

如果需要访问多个方法但只关心listen,可以用mockImplementation返回一个包含listen和其他未用方法占位的对象,所有未用方法用jest.fn()填充即可。

import { NestFactory, INestApplication } from '@nestjs/core';

jest.mock('@nestjs/core');

const mockedNestFactory = jest.mocked(NestFactory);

test('测试应用启动流程', async () => {
  const mockedListen = jest.fn().mockResolvedValue(true);
  
  mockedNestFactory.create.mockImplementation(async () => {
    return {
      listen: mockedListen,
      // 用jest.fn()占位未用到的必要方法
      close: jest.fn(),
      init: jest.fn(),
      getHttpAdapter: jest.fn(),
    } as INestApplication;
  });

  // 执行测试逻辑
  const app = await NestFactory.create();
  await app.listen(3000);
  
  expect(mockedListen).toHaveBeenCalledWith(3000);
});

内容的提问来源于stack exchange,提问作者Mansur Ali Koroglu

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.22 20:05:30