在执行节点模块的单元测试时,是否可以选择性地禁用Winston日志记录?
理想情况下,我希望在应用程序运行时记录信息和调试目的,但是在我运行测试时不要弄乱表示单元测试结果。
我对winston的使用是我模块的内部,如下所示:
// MyModule.js
var logger = require('winston');
module.exports = function() {
// does some stuff
// and logs some stuff like so:
logger.log('an informational message');
}
// MyModuleTest.js
describe('MyModule', fucntion() {
it('should do some stuff', function() {
var myModuleUnderTest = require('MyModule');
// some tests
}
}
答案 0 :(得分:15)
Winston传输具有您可以设置的silent
属性,这可能比删除整个传输更好。
我为传输添加一个名称就像这样容易一点:
var logger = new winston.Logger();
logger.add(winston.transports.Console, {
name: 'console.info',
colorize: true,
showLevel: true,
formatter: consoleFormatter,
})
然后在测试或设置中,我可以选择性地打开和关闭登录:
logger.transports['console.info'].silent = true // turns off
logger.transports['console.info'].silent = false // logging back on
答案 1 :(得分:8)
如果你正在使用Jest,你可以这样禁用它:
设置在jest运行测试之前运行的设置文件。在package.json
:
{
"jest": {
"setupFiles": ["<rootDir>/jest-set-up/index.js"]
}
}
在jest-set-up/index.js
:
import winston from 'winston'
winston.remove(winston.transports.Console)
答案 2 :(得分:7)
对不起,我知道这是一个老问题。
我做的有点难看,但允许我继续正常使用Jest的<img src= '<?php echo $image_path;?>'width="200" height="200" alt=""/>
选项。我只是将温斯顿的--silent
设置为silent
。例如:
process.argv.indexOf("--silent") >= 0
答案 3 :(得分:2)
创建记录器:
const logger = createLogger({
level: "info",
format: format.json(),
transports: []
});
使所有记录保持沉默:
logger.transports.forEach((t) => (t.silent = true));
答案 4 :(得分:1)
设置对我来说不起作用,我使用的是winston v3.1.0,有一种创建记录器的新方法。
在Winston网站上:https://github.com/winstonjs/winston
推荐使用winston的方法是创建自己的记录器。最简单的方法是使用winston.createLogger:
const logger = winston.createLogger({
level: 'info',
format: winston.format.json(),
transports: [
//
// - Write to all logs with level `info` and below to `combined.log`
// - Write all logs error (and below) to `error.log`.
//
new winston.transports.File({ filename: 'error.log', level: 'error' }),
new winston.transports.File({ filename: 'combined.log' })
]
});
//
// If we're not in production then log to the `console` with the format:
// `${info.level}: ${info.message} JSON.stringify({ ...rest }) `
//
if (process.env.NODE_ENV !== 'production') {
logger.add(new winston.transports.Console({
format: winston.format.simple()
}));
}
所以我在logger.js中完成
if (process.env.NODE_ENV === 'test') {
return winston.createLogger({
transports: [ new winston.transports.Console({ level: 'error'}) ]
});
}
这将停止所有日志消息,除非出现错误,我希望借此错误来调试任何问题。
希望这会有所帮助。
答案 5 :(得分:1)
这是我的设置:
const { createLogger, format, transports, config } = require("winston");
let level, silent;
switch (process.env.NODE_ENV) {
case "production":
level = "warning";
silent = false;
break;
case "test":
level = "emerg";
silent = true;
break;
default:
level = "debug";
silent = false;
break;
}
const options = {
console: {
level,
silent,
handleExceptions: true,
format: format.combine(
format.colorize(),
format.splat(),
format.printf(
info => `${new Date().toISOString()} ${info.level}: ${info.message}`,
),
),
},
};
const logger = createLogger({
levels: config.syslog.levels,
transports: [new transports.Console(options.console)],
exitOnError: false,
});
module.exports = logger;
答案 6 :(得分:1)
我意识到这已经很晚了,但是我只是想和jest分享我的解决方案,因为我对这里找到的解决方案并不完全满意。我不能说我的解决方案非常优雅,可能在我仍在学习TDD时就隐藏了一些代码味道,但它确实有效。
在我的工作中,我经常想登录到通过winston.transports.File(filename: "<filename>")
传输指定的文件。假设我的日志文件是info.log
当然,在测试期间,我不需要
info.log
info.log
(如果不存在则创建)。这样做是为了避免产生副作用。上面的答案以及嘲笑足以避免1.,但由于某些原因不能避免2.(在下面解释原因)。
我设置项目的方式通常是
src
├── app.js
├── services
│ ├── logging
│ │ ├── logger.js
│ │ └── logger_utils.js
│ ├── foo.js
│ ├── bar.js
│ └── etc.js
├── tests
│ ├── foo.test.js
│ ├── bar.test.js
│ └── etc.test.js
└── logs
└── info.log
主要关注与日志相关的文件。 logger.js
是我实例化并随后导出winston Logger对象的地方。然后,我在logger_utils.js
中编写帮助程序功能,以实现模块化和更轻松的测试。
出现问题时,logger.js
包含在
problematic_logger.js
const winston = require("winston");
const path = require("path");
// define the log file directory
const log_dir = path.resolve(__dirname, "./../../logs/info.log");
// create logger
const logger = winston.createLogger({
transports: [
new winston.transports.File({
filename: log_dir
})
]
});
// export it
module.exports = logger;
然后我在logger_utils.js
中需要它,而在其他任何模块脚本中都将需要它。因此,在测试中(除了测试logger_utils.js
之外,我只需要模拟logger_utils.js
中包含的函数,而不必担心logger.js
,因为它仅由{{1 }}。
现在,我对此并不完全确定,但是我认为尽管进行了模拟和沉默,但上面定义的2.仍然失败,因为仍在调用logger_utils.js
,并且我相信即使在设置了--silent标志。我不知道这是否是正确的,但是上述解决方案无法正常工作。
因此,(受this answer的启发),我决定要做的只是在测试时不创建任何winston对象。为此,我将winston.createLogger()
文件更改为
logger.js
fixed_logger.js
(运行const winston = require("winston");
const path = require("path");
// define the log file directory
const log_dir = path.resolve(__dirname, "../../logs/info.log");
// if we are testing, don't create any winston object
if (process.env.NODE_ENV === "test") {
// export
module.exports = {};
} else {
// behave normally otherwise
// create winston logger
const logger = winston.createLogger({
transports: [
new winston.transports.File({
filename: log_dir
})
]
});
// export it
module.exports = logger;
}
或NODE_ENV
等时,{npm test
会自动设置为“ test”)
我们仍然需要导出一些内容,以便logger_utils.js在测试时不会损坏,因此我们导出了一个空对象。很好,因为会被嘲笑。
无论如何,这是我对stackoverflow的第一个答案。我希望这不是灾难性的事情,让我知道是否有人需要进一步的细节。
答案 7 :(得分:1)
我们在测试中使用了 silent
属性:
import logger from './my-defined-winston-logger'
//...
beforeAll(() => {
logger.silent = true;
})
afterAll(() => {
logger.silent = false;
})