Search code examples
nestjsts-jest

How to mock NestJS built-in Logger in Jest


I have a controller that uses NestJS built-in Logger via dependency injection in constructor of the controller:

  constructor(private readonly logger: Logger) 

I want to be able to mock it in my Jest tests to see which methods and with what arguments are being called during logging. I tried this syntax:

providers[{
    provide: Logger,
    useValue: {
      log: jest.fn(),
    }
}]

In that case this line:

    expect(Logger).toHaveBeenCalledTimes(1);

Returns: Matcher error: received value must be a mock or spy function

Any help will be highly appreciated!


Solution

  • In your test, you should get the logger back out of the DI context using moduleFixture.get(Logger) (or something very similar) and then check expect(logger.log).toHaveBeenCalledTimes(1). Logger itself is a class, not a spy or mock, so Jest doesn't know what to do with that.

    Full solution that worked:

    import { Test } from '@nestjs/testing';
    let logger: Logger;
    
    beforeEach(async () => {
      const moduleRef = await Test.createTestingModule({
        providers: [  
          {
            provide: Logger,
            useValue: {
              log: jest.fn(),
            },
          },
        ],
      }).compile();
      logger = moduleRef.get<Logger>(Logger);
    });
    

    And then later in the test itself:

    expect(logger.log).toHaveBeenCalledTimes(1);
    expect(logger.log).toHaveBeenCalledWith('Your log message here')