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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With