javascriptunit-testingjestjsnestjsrollbar

How to mock third party library using jest


I am developing a node.js application using nestjs I have a class called LoggerService as below

export class LoggerService {

    private logger: Rollbar;

    constructor() {
        this.logger = this.setupLogger();
    }

    critical(...args: Array<string | Error | object | Date | any[]>) {
        this.logger.error(...args);
    }

    private setupLogger(): Rollbar {
        if (this.logger == null) {

            this.logger = new Rollbar({
                accessToken: 'token',
                environment: 'dev',
                captureUncaught: true,
                captureUnhandledRejections: true,
            });

        }

        return this.logger;
    }

Now I am writing unit test for this class using jest as below.

describe('LoggerService.log', () => {
  let service: LoggerService;

  beforeEach(async () => {

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

    service = module.get<LoggerService>(LoggerService);
  });

  it('critical', () => {
    service.critical('error','message');
    expect(???).toHaveBeenCalledWith('error', 'message')
  })

);

My question is how to check(expect) if logger.error is called, or how to mock Rollbar in this class.


Solution

  • 1) Provide your external dependency/library as an injectable token in your module

    @Module({
      providers: [
        {
          provide: 'Rollbar',
          useFactory: async (configService: ConfigService) => new Rollbar({
                    accessToken: configService.accessToken,
                    environment: configService.environment,
                    captureUncaught: true,
                    captureUnhandledRejections: true,
                }),
          inject: [ConfigService],
        },
      ]
    

    2) Inject it in your LoggerService instead of creating it

    export class LoggerService {
        constructor(@Inject('Rollbar') private logger: Rollbar) {
        }
    

    3) Now you can mock your dependency in your test

    const module: TestingModule = await Test.createTestingModule({
      providers: [
        LoggerService,
        { provide: 'Rollbar', useFactory: rollbarMockFactory },
      ],
    }).compile();