【发布时间】:2023-03-29 11:18:01
【问题描述】:
我有一个使用 Winston NodeJs 包的记录器。记录器执行额外的逻辑,我希望进行单元测试以确保将正确的数据传递给 Winston。但是,由于我已经设置了外部传输(例如 Firehose),因此不需要调用它们。
我没有通过构造函数将 Winston 作为依赖项传递,但我尝试了将 createLogger 方法、log 方法和 Winston 作为一个整体进行存根,就像我通常在存根依赖项时所做的那样。
createStubbedInstance 方法不适用于 Winston(或者,我无法让它工作),因为 Winston 不是作为类导出,而是作为命名空间导出。
import { Logger, ILoggerConfig } from './src';
import * as winston from 'winston'
describe('Logger', () => {
let loggerConfig: ILoggerConfig;
let sandbox: sinon.SinonSandbox;
beforeEach(() => {
sandbox = sinon.createSandbox();
loggerConfig = {
correlationId: faker.random.uuid(),
action: 'GET',
};
sandbox = sinon.createSandbox();
winstonStub = sandbox.stub(winston);
winstonStub.createLogger.resolves();
winstonStub.log.resolves();
...
});
it('should log with INFO log level', () => {
const logger = new Logger(loggerConfig);
logger.info('Hello there!');
sinon.assert.calledOnce(winstonStub.log);
sinon.assert.calledWith(winsonStub.log, sinon.match.has("level", 'info'))
});
import { Logger, ILoggerConfig } from './src';
import * as winston from 'winston'
describe('Logger', () => {
let loggerConfig: ILoggerConfig;
let sandbox: sinon.SinonSandbox;
beforeEach(() => {
sandbox = sinon.createSandbox();
loggerConfig = {
correlationId: faker.random.uuid(),
action: 'GET',
};
sandbox = sinon.createSandbox();
winstonStub = sandbox.stub(winston, 'createLogger').resolves({ log: sanbox.stub() });
...
});
it('should log with INFO log level', () => {
const logger = new Logger(loggerConfig);
logger.info('Hello there!');
sinon.assert.calledOnce(winstonStub);
});
我希望能够断言存根会被调用一定次数。但是,存根的调用计数始终为 0,并且我收到一条错误消息,表明 Winston 由于权限问题而无法发布到 Firehose。我还设置了控制台传输,并且在我不应该看到的时候仍然在控制台中看到日志。
【问题讨论】:
-
您能发布一些您正在尝试测试的代码库吗?基本上,如果你
require()你的类,requires 你的记录器,在测试文件的顶部,那么在记录器中存根任何东西都不会做任何事情,因为它已经导入到基类中,并且你的存根不会影响它。您需要在导入基类之前存根记录器,或者在基类的构造函数中注入记录器,然后对其进行测试。你觉得这有意义吗? -
是的。我正在为记录器本身编写单元测试。我会更新一些代码来展示我的测试是什么样子的
-
对于任何将来来这里的人。我想到了。奇怪的是,
import * as winston from 'winston'的语法是只读的。我在我的测试文件和应用程序文件中都将它更改为import winston from 'winston',并且能够成功地存根我需要的属性。