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

如何在NestJS中为端到端测试Mock PrismaService?

在NestJS E2E测试中Mock全局PrismaService(针对CategoryModule)

因为你已经把PrismaModule设为全局模块,CategoryModule会自动注入PrismaService,要在E2E测试里Mock它,有两种实用方法:

方法一:直接在测试模块中覆盖Provider

这是最直接的方式,在E2E测试文件里定义Mock的PrismaService,然后通过overrideProvider替换全局服务:

import { Test } from '@nestjs/testing';
import { INestApplication } from '@nestjs/common';
import { PrismaService } from 'nestjs-prisma';
import { CategoryModule } from '../src/category/category.module';
import * as request from 'supertest';

// 按需定义Mock的PrismaService方法
const mockPrismaService = {
  category: {
    findMany: jest.fn().mockResolvedValue([{ id: 1, name: '测试分类' }]),
    create: jest.fn().mockResolvedValue((dto) => ({ id: 2, ...dto })),
    // 加你需要测试的其他方法,比如findUnique、update等
  },
};

describe('CategoryModule (E2E)', () => {
  let app: INestApplication;

  beforeEach(async () => {
    const moduleFixture = await Test.createTestingModule({
      imports: [CategoryModule],
    })
      // 覆盖全局的PrismaService为Mock实例
      .overrideProvider(PrismaService)
      .useValue(mockPrismaService)
      .compile();

    app = moduleFixture.createNestApplication();
    await app.init();
  });

  afterEach(async () => {
    await app.close();
    // 重置Mock调用记录,避免测试互相干扰
    jest.clearAllMocks();
  });

  it('/categories (GET) 应该返回分类列表', async () => {
    return request(app.getHttpServer())
      .get('/categories')
      .expect(200)
      .expect([{ id: 1, name: '测试分类' }]);
  });

  it('/categories (POST) 应该创建新分类', async () => {
    const newCategory = { name: '新分类' };
    return request(app.getHttpServer())
      .post('/categories')
      .send(newCategory)
      .expect(201)
      .expect({ id: 2, ...newCategory });
  });
});

方法二:创建复用的Mock模块(适合多测试场景)

如果多个E2E测试都需要Mock PrismaService,可以抽成一个测试专用模块,方便复用和修改:

// test/mock-prisma.module.ts
import { Module } from '@nestjs/common';
import { PrismaService } from 'nestjs-prisma';

// 基础Mock实现
const baseMockPrisma = {
  category: {
    findMany: jest.fn().mockResolvedValue([]),
    create: jest.fn().mockResolvedValue((dto) => ({ id: Date.now(), ...dto })),
  },
  // 其他模型的基础Mock
};

@Module({
  providers: [
    {
      provide: PrismaService,
      useValue: baseMockPrisma,
    },
  ],
  exports: [PrismaService],
})
export class MockPrismaModule {}

然后在测试里导入这个模块,还能针对当前测试需求覆盖特定方法:

// category.e2e-spec.ts
import { MockPrismaModule } from '../test/mock-prisma.module';

// ...其他导入

describe('CategoryModule (E2E)', () => {
  let app: INestApplication;

  beforeEach(async () => {
    const moduleFixture = await Test.createTestingModule({
      imports: [CategoryModule, MockPrismaModule],
    })
      // 针对当前测试覆盖findUnique方法
      .overrideProvider(PrismaService)
      .useValue({
        ...baseMockPrisma,
        category: {
          ...baseMockPrisma.category,
          findUnique: jest.fn().mockResolvedValue({ id: 1, name: '指定分类' }),
        },
      })
      .compile();

    app = moduleFixture.createNestApplication();
    await app.init();
  });

  // ...测试用例
});

关键注意点

  • 每次测试结束后一定要重置Mock(jest.clearAllMocks()),防止不同测试的调用记录互相干扰。
  • Mock方法要和业务逻辑匹配,比如如果你的服务里调用了prisma.category.findUnique,就要在Mock里实现这个方法,否则会报错。
  • 复杂场景下可以用jest.fn().mockImplementation()替代mockResolvedValue,编写更灵活的Mock逻辑。

内容的提问来源于stack exchange,提问作者JuanDa237

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.07 23:50:42