如何测试NestJS Logger调用及异常抛出场景?
问题根源与解决方案
核心问题
- Logger实例不匹配:你的
TestService中是直接new Logger(...)创建实例,而非通过Nest的依赖注入获取,导致测试模块中提供的Logger mock完全没被用到,测试里的serviceLogger.error永远不会被调用。 - 测试执行顺序错误:失败用例中先验证Logger调用,再执行方法,此时方法还未运行,自然不会触发Logger调用。
解决方案步骤
1. 修改TestService,通过依赖注入获取Logger
将TestService中直接创建Logger的方式改为Nest支持的依赖注入,这样测试时才能替换为mock实例。推荐使用@Logger装饰器:
import { Injectable, Logger } from '@nestjs/common'; import { InjectRepository } from '@nestjs/typeorm'; import { Repository } from 'typeorm'; import { TestEntity } from './test.entity'; import { CreateTestDto } from './dto/create-test.dto'; import { InternalServerErrorException } from '@nestjs/common'; @Injectable() export class TestService { // 替换原new Logger的方式,用@Logger装饰器注入带context的Logger @Logger('TestSuiteRepository') private readonly logger: Logger; constructor( @InjectRepository(TestEntity) private readonly repo: Repository<TestEntity>, ) {} async createTest(createTestDto: CreateTestDto): Promise<TestEntity> { const { organization, title, description, questions } = createTestDto; try { const test = this.repo.create({ organization, title, description, questions, }); await this.repo.save(test); return test; } catch (ex: unknown) { const stack = ex instanceof Error ? ex.stack : ''; const msg = ex instanceof Error ? ex.message : ''; this.logger.error( `Failed to create Test! Data: ${JSON.stringify(createTestDto)}`, msg, stack, ); throw new InternalServerErrorException(); } } }
2. 调整测试用例的执行逻辑
修正测试顺序:先执行方法并等待异常抛出,再验证Logger的调用。同时移除不必要的repo.save mock(因为repo.create抛出错误后,save不会执行):
it('should log and throw an error when repo.create() fails', async () => { const newTest: CreateTestDto = { organization: 'abcd-efgh-ij', title: 'My Title', description: 'Foo', }; // 让repo.create抛出错误 jest.spyOn(repo, 'create').mockImplementation(() => { throw new Error('Create failed!'); }); // 先执行方法,等待异常抛出 await expect(service.createTest(newTest)).rejects.toThrow(InternalServerErrorException); // 再验证Logger.error是否被调用 expect(serviceLogger.error).toHaveBeenCalled(); // 可选:验证Logger调用的参数是否符合预期 expect(serviceLogger.error).toHaveBeenCalledWith( `Failed to create Test! Data: ${JSON.stringify(newTest)}`, 'Create failed!', expect.any(String), // 匹配任意栈信息字符串 ); });
内容的提问来源于stack exchange,提问作者Chris Barr
相关产品推荐
相关产品推荐

