[FIXED] NestJS test cannot resolve PinoLogger dependency

Issue

On NestJS application startup I am creating few db tables (using TypeORM) and have written service file init-db.service.ts for the same. The service file implements OnApplicationBootstrap interface and onApplicationBootstrap method is called once the application has fully started and is bootstrapped.
I am trying to write a unit test for the service file, but is unable to resolve PinoLogger dependency while creating Testing Module. Please checkout below sample code:

Service file init-db.service.ts:

import {ConfigService} from '@nestjs/config';
import {PinoLogger} from 'nestjs-pino';
import {Injectable, OnApplicationBootstrap} from '@nestjs/common';

@Injectable()
export class InitDB implements OnApplicationBootstrap {
  constructor(private readonly logger: PinoLogger, private readonly configService: ConfigService) {}

  onApplicationBootstrap() {
    this.someMethod();
  }


  async someMethod(): Promise<void> {
    // code to create tables...
  }
}

Unit test file init-db.service.spec.ts:

import {ConfigService} from '@nestjs/config';
import {Test, TestingModule} from '@nestjs/testing';
import {InitDB} from './init-db.service';
import {getLoggerToken, PinoLogger} from 'nestjs-pino';

const mockLogger = {
// mock logger functions
};

describe('InitDB', () => {
  jest.useFakeTimers();

  let configService: ConfigService;
  let service: InitDB;

  beforeEach(async () => {
    const module: TestingModule = await Test.createTestingModule({
      providers: [
        {
          provide: getLoggerToken(InitDB.name),  // <-------- PinoLogger dependency
          useValue: mockLogger,
        },
        InitDB,
        ConfigService,
      ],
    }).compile();

    service = module.get<InitDB>(InitDB);
    configService = module.get<ConfigService>(ConfigService);
  });

  afterEach(() => {
    jest.clearAllMocks();
  });

  it('should be defined', () => {
    expect(service).toBeDefined();
  });

});

Error Message:

Nest can't resolve dependencies of the BootstrapService (?, ConfigService). Please make sure that the argument PinoLogger at index [0] is available in the RootTestModule context.

    Potential solutions:
    - If PinoLogger is a provider, is it part of the current RootTestModule?
    - If PinoLogger is exported from a separate @Module, is that module imported within RootTestModule?
      @Module({
        imports: [ /* the Module containing PinoLogger */ ]
      })

I have already passed PinoLogger at index [0], but the unit test still fails to resolve the dependency.

Solution

Please note that you don’t use @InjectPinoLogger but you are trying to mock it as if you have used it.
You could either provide PinoLogger as a dependency:

    const module: TestingModule = await Test.createTestingModule({
      providers: [
        PinoLogger,
        InitDB,
        ConfigService,
      ],
    }).compile();

or use @InjectPinoLogger in your class constructor:

export class InitDB implements OnApplicationBootstrap {
  constructor(
    @InjectPinoLogger(InitDB.name)
    private readonly logger: PinoLogger, 
    private readonly configService: ConfigService
    ) {}
}

Answered By – Dimi Vi

Answer Checked By – Terry (Easybugfix Volunteer)

Leave a Reply

(*) Required, Your email will not be published