This question already exists, but it is marked as solved and the solution doesn't work at all for me.
I want to mock a nest-winston logger that is a dependency of a provider in nestjs.
@Controller('builder/instance')
export class InstanceController {
private executor: Executor;
constructor(
@Inject(WINSTON_MODULE_NEST_PROVIDER) private readonly logger: Logger,
private stripeService: StripeService,
private instanceService: InstanceService,
private organizationService: OrganizationService,
private executorFactory: ExecutorFactory,
private socketService: SocketService,
private auditLogService: AuditLogService,
) {
this.logger.log("hello world!", InstanceController.name);
this.executor = this.executorFactory.getExecutor();
// ...
}
}
The authors solution was to pass in the loggers token as a provider to the module with an empty useValue. I assume it is because they didn't want to actually call it, but just supply the dependency for one of the providers they mock.
describe('InstanceController', () => {
let controller: InstanceController;
const mockStripeService = {};
const mockInstanceService = {};
const mockOrganizationService = {};
const mockExecutorFactory = {};
const mockSocketService = {};
const mockAuditLogService = {};
beforeEach(async () => {
const module: TestingModule = await Test.createTestingModule({
// imports: [AccountModule],
controllers: [InstanceController],
providers: [
{ provide: WINSTON_NEST_MODULE_PROVIDER, useValue: {} },
StripeService,
InstanceService,
OrganizationService,
ExecutorFactory,
SocketService,
AuditLogService,
],
})
.overrideProvider(StripeService)
.useValue(mockStripeService)
.overrideProvider(InstanceService)
.useValue(mockInstanceService)
.overrideProvider(OrganizationService)
.useValue(mockOrganizationService)
.overrideProvider(ExecutorFactory)
.useValue(mockExecutorFactory)
.overrideProvider(SocketService)
.useValue(mockSocketService)
.overrideProvider(AuditLogService)
.useValue(mockAuditLogService)
.compile();
controller = module.get<InstanceController>(InstanceController);
});
it('should be defined', () => {
expect(controller).toBeDefined();
});
});
However, when trying to run the tests, it tries to find this.logger.log
and when this.logger
returns as {}
it says this.logger.log is not a function
.
Does anyone know of a way to properly mock the logger dependency and can help me with this? The auto mocking described in nestjs documentation did not work for me either.
I am very new with jest and nestjs, and my plaster solution thusfar is to replace the empty useValue with
{
log: jest.fn(),
debug: jest.fn(),
info: jest.fn(),
warn: jest.fn(),
error: jest.fn(),
}
, which is just... awful. Help will be greatly appreciated!
First off, I would suggest not setting every provider and then using override
provider. Instead, use a simple custom provider like
{
provide: StripeService,
useValue: mockStripeService
}
Much less boilerplate when you have this many services. I keep the override*()
methods for my integration and e2e tests where I need to override a provider that is registered by another module.
Second, if all you end up using in your method is this.logger.log
then mockign log
to jest.fn()
is a fine approach.
{
provide: WINSTON_NEST_MODULE_PROVIDER,
useValue: { log: jest.fn() }
}
That will allow your code to run and nothing to log out to the console from the logger.