我尝试模拟一个 * winston.logger * 示例,它封装在一个用NestJS创建的服务类中。我在下面包含了我的代码。
我无法从服务类中触发被模拟的日志记录器示例。有人能解释一下我哪里出错了吗?
import * as winston from 'winston';
import { loggerOptions } from '../logger/logger.config';
import { LoggingService } from '../logger/logger.service';
const logger: winston.Logger = winston.createLogger(loggerOptions);
// trying to mock createLogger to return a specific logger instance
const winstonMock = jest.mock('winston', () => (
{
format: {
colorize: jest.fn(),
combine: jest.fn(),
label: jest.fn(),
timestamp: jest.fn(),
printf: jest.fn()
},
createLogger: jest.fn().mockReturnValue(logger),
transports: {
Console: jest.fn()
}
})
);
describe("-- Logging Service --", () => {
let loggerMock: winston.Logger;
test('testing logger log function called...', () => {
const mockCreateLogger = jest.spyOn(winston, 'createLogger');
const loggingService: LoggingService = LoggingService.Instance;
loggerMock = mockCreateLogger.mock.instances[0];
expect(loggingService).toBeInstanceOf(LoggingService)
expect(loggingService).toBeDefined();
expect(mockCreateLogger).toHaveBeenCalled()
// spy on the winston.Logger instance within this test and check
// that it is called - this is working from within the test method
const logDebugMock = jest.spyOn(loggerMock, 'log');
loggerMock.log('debug','test log debug');
expect(logDebugMock).toHaveBeenCalled();
// now try and invoke the logger instance indirectly through the service class
// check that loggerMock is called a second time - this fails, only called once
// from the preceding lines in this test
loggingService.debug('debug message');
expect(logDebugMock).toHaveBeenCalledTimes(2);
});
...
日志服务调试方法代码
public debug(message: string) {
this.logger.log(
{
level: types.LogLevel.DEBUG,
message: message,
meta: {
context: this.contextName
}
}
);
}
更新日期:2019年3月9日
重构了我的nestjs LoggingService,以便在构造函数中依赖注入winston日志记录器示例,以便于单元测试。这使我能够在winston日志记录器的log方法上使用 jest.spyOn,并检查它是否已在服务示例中调用:
// create winstonLoggerInstance here, e.g. in beforeEach()....
const winstonLoggerMock = jest.spyOn(winstonLoggerInstance, 'log');
serviceInstance.debug('debug sent from test');
expect(winstonLoggerMock).toHaveBeenCalled();
3条答案
按热度按时间wmomyfyw1#
我已经测试了您的代码,似乎在使用jest.mock时存在多个问题。
为了正确地模拟一个模块,你必须在导入它之前先模拟它。这是一个内部机制(jest如何模拟模块),你必须遵守这个规则。
正如您所看到的,您不能使用winston示例作为mock的返回值,但是不用担心,也可以mock该示例(您在前面的代码示例中也可以看到)。
最后,你不需要窥探你曾经嘲笑过什么,所以直接问嘲笑者就行了。
完整的代码在这里:
我将最后一个Assert更改为一个,因为我在测试中调用了
log
,在LoggingService中调用了debug
。这是我使用的日志服务:
好好玩!
x7rlezfr2#
我最近遇到了同样的问题,并通过使用jest.spyOn和我的自定义日志记录器解决了这个问题。
注意:您不必对winston.createLogger()进行单元测试。Winston模块有自己的单元测试来涵盖该功能。
记录错误的某个函数(例如
./controller.ts
):该函数的测试文件(即'./tests/controller.test.ts):
o7jaxewo3#
在所选答案的基础上,我还要补充一点,你不需要模拟整个Winston对象,你可以模拟某个部分,如下所示:
这样的话,你就可以专注于嘲笑这一部分,而其他部分则完好无损。