如何测试PrismaService中enableShutdownHooks的app.close()调用
PrismaService单元测试:覆盖beforeExit回调中的app.close()
问题场景
我的PrismaService代码如下:
import { INestApplication, Injectable } from '@nestjs/common'; import { PrismaClient } from '@prisma/client'; @Injectable() export class PrismaService extends PrismaClient { async enableShutdownHooks(app: INestApplication) { this.$on('beforeExit', async () => { await app.close(); }); } }
当前的单元测试代码无法覆盖第8行的await app.close()——要么mock$on时自己手动调用了app.close()(测的是mock逻辑而非原代码),要么不mock的话beforeExit事件永远不会触发,导致这行代码没执行。
解决方案
核心思路是捕获$on注册的回调函数,手动触发它,这样就能让原代码里的app.close()执行,从而覆盖到目标代码。
修改后的测试代码如下:
import { INestApplication } from '@nestjs/common'; import { Test, TestingModule } from '@nestjs/testing'; import { PrismaService } from './prisma.service'; const MockApp = jest.fn<Partial<INestApplication>, []>(() => ({ close: jest.fn(), })); describe('PrismaService', () => { let service: PrismaService; let app: Partial<INestApplication>; beforeEach(async () => { app = MockApp(); const module: TestingModule = await Test.createTestingModule({ providers: [PrismaService], }).compile(); service = module.get<PrismaService>(PrismaService); }); it('should be defined', () => { expect(service).toBeDefined(); }); describe('enableShutdownHooks', () => { it('should register beforeExit hook and call app.close when triggered', async () => { // 监听$on方法,保留原实现 const onSpy = jest.spyOn(service, '$on').mockImplementation(jest.fn()); await service.enableShutdownHooks(app as INestApplication); // 验证$on被正确调用,事件名为beforeExit expect(onSpy).toHaveBeenCalledWith('beforeExit', expect.any(Function)); // 取出注册的回调函数 const beforeExitCallback = onSpy.mock.calls[0][1] as () => Promise<void>; // 手动触发回调 await beforeExitCallback(); // 验证原代码中的app.close被调用 expect(app.close).toHaveBeenCalledTimes(1); onSpy.mockRestore(); }); }); });
关键说明
- 不再mock
$on的实现,而是用jest.spyOn监听调用,通过mock.calls获取到注册的beforeExit回调函数。 - 手动执行这个回调,就能触发原代码里的
await app.close(),自然覆盖到目标行。 - 既验证了
$on的调用逻辑,又验证了回调函数的实际执行效果,完全贴合原代码逻辑。
内容的提问来源于stack exchange,提问作者Diogo Santos
相关产品推荐
相关产品推荐

