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

如何测试NestJS Logger调用及异常抛出场景?

问题根源与解决方案

核心问题

  1. Logger实例不匹配:你的TestService中是直接new Logger(...)创建实例,而非通过Nest的依赖注入获取,导致测试模块中提供的Logger mock完全没被用到,测试里的serviceLogger.error永远不会被调用。
  2. 测试执行顺序错误:失败用例中先验证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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.09 14:44:59