运行单元测试时禁用winston日志记录?

时间:2016-07-13 23:25:08

标签: node.js unit-testing winston

在执行节点模块的单元测试时,是否可以选择性地禁用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
  }
}   

8 个答案:

答案 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,你可以这样禁用它:

  1. 设置在jest运行测试之前运行的设置文件。在package.json

    {
        "jest": {
            "setupFiles": ["<rootDir>/jest-set-up/index.js"]
        }
    }
    
  2. 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

当然,在测试期间,我不需要

  1. 要写入此info.log
  2. 的日志
  3. 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;
})