如何在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
相关产品推荐
相关产品推荐

