Disable winston logging when running unit tests?

前端 未结 7 1175
暗喜
暗喜 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: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: "") 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.

提交回复
热议问题