Disable winston logging when running unit tests?

前端 未结 7 1062
暗喜
暗喜 2021-02-05 03:18

Can Winston logging be selectively disabled when executing unit tests of a node module?

Ideally, I\'d like to have logging for informational and debug purposes when the

相关标签:
7条回答
  • 2021-02-05 03:34

    Create a logger:

    const logger = createLogger({
        level: "info",
        format: format.json(),
        transports: []
    });
    

    Silence all logging:

    logger.transports.forEach((t) => (t.silent = true));
    
    0 讨论(0)
  • 2021-02-05 03:43

    Sorry, I know this is a bit of an old question.

    What I do is a bit ugly, but allows me to keep using Jest's --silent option normally. I just set Winston's silent to process.argv.indexOf("--silent") >= 0. For example:

    const logger = new winston.Logger({
      …,
      transports: [
        new winston.transports.Console({
          …,
          silent: process.argv.indexOf("--silent") >= 0,
        }),
      ],
    });
    
    0 讨论(0)
  • 2021-02-05 03:47

    Here's my setup:

    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;
    
    0 讨论(0)
  • 2021-02-05 03:49

    If you are using Jest, you can disable it like so:

    1. Set set up files to be run before jest runs the test. In package.json:

      {
          "jest": {
              "setupFiles": ["<rootDir>/jest-set-up/index.js"]
          }
      }
      
    2. In jest-set-up/index.js:

      import winston from 'winston'
      winston.remove(winston.transports.Console)
      
    0 讨论(0)
  • 2021-02-05 03:49

    I realise that this is quite late but I just wanted to share my solution with using jest, since I wasn't entirely satisfied with the solutions found here. I can't say my solution is very elegant and may just be hiding some code smell as I'm still learning TDD, but it works.

    In my work I often want to log to a file specified via a winston.transports.File(filename: "<filename>") transport. Let's say my log file is info.log

    Of course, during testing, I don't want

    1. logs to be written to this info.log
    2. info.log to be created if it doesn't exist.

    This is so to avoid side-effects. The answers above along with mocking were enough for avoiding 1. but for some reason did not avoid 2. (explained why below) .

    The way I set up my projects is usually as such

       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
    

    Focus mostly on the log-related files. logger.js is where I instantiate and subsequently export the winston Logger object. I then write helper functions in logger_utils.js for modularity and easier testing.

    When my issue was appearing, logger.js consisted in

    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;
    

    I then required it in logger_utils.js which would in turn be required in any other modules scripts. So, in testing (apart from testing logger_utils.js), I only need to mock functions contained in logger_utils.js, with no need to worry about logger.js, since it is only called by logger_utils.js.

    Now, I'm not entirely sure about this, but I think 2. defined above still failed despite the mocks and the silencing because winston.createLogger() was still being called, and I believe this will create a file even when a --silent flag is set. I don't know if this is true, but nevertheless the solutions above weren't working.

    So, (inspired by this answer) what I decided to do is to simply not create any winston object when testing. I did this by changing my logger.js file to

    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 is automatically set to "test" when running npm test or npm run test:watch etc.)

    We still need to export something for logger_utils.js to not break when testing it, so we export an empty object. This is fine since it will be mocked.

    Anyway, that's my first answer on stackoverflow out of the way. I hope it wasn't too disastrous, let me know if anyone wants further details.

    0 讨论(0)
  • 2021-02-05 03:50

    Winston transports have a silent property that you can set, which is probably a little nicer than removing the entire transport.

    I add a name to the transports to make is a little easier like this:

    var logger = new winston.Logger();
    
    logger.add(winston.transports.Console, {
        name: 'console.info',
        colorize: true,
        showLevel: true,
        formatter: consoleFormatter,
    })
    

    Then in the test or set-up I can selectively turn logging on and off with:

    logger.transports['console.info'].silent = true  // turns off
    logger.transports['console.info'].silent = false // logging back on
    
    0 讨论(0)
提交回复
热议问题