Отключить ведение журнала Winston при выполнении модульных тестов?

Можно ли выборочно отключить ведение журнала Winston при выполнении модульных тестов модуля node?

В идеале, я хотел бы иметь журнал для информационных и отладочных целей, когда приложение работает, но будет подавлено, чтобы не загромождать результаты презентации unit test при выполнении моих тестов.

Мое использование 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
  }
}   

Ответ 1

У транспортных средств 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

Ответ 2

Если вы используете 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)
    

Ответ 3

Извините, я знаю, что это немного старый вопрос.

То, что я делаю, немного уродливо, но позволяет мне обычно использовать параметр Jest --silent. Я просто установил Winston silent в process.argv.indexOf("--silent") >= 0. Например:

const logger = new winston.Logger({
  …,
  transports: [
    new winston.transports.Console({
      …,
      silent: process.argv.indexOf("--silent") >= 0,
    }),
  ],
});

Ответ 4

Создать регистратор:

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

Тишина всех логов:

logger.transports.forEach((t) => (t.silent = true));

Ответ 5

Вот моя настройка:

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

У меня не сработали настройки, я использую Winston v3.1.0, есть новый способ создания регистраторов.

С сайта Уинстон: 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'}) ]
    });
}

Это останавливает все сообщения журнала, если у вас нет ошибки, которую я хотел бы видеть, чтобы помочь с отладкой любых проблем.

Надеюсь это поможет.

Ответ 7

Я понимаю, что уже довольно поздно, но я просто хотел поделиться своим решением с использованием Jest, так как я не был полностью удовлетворен решениями, найденными здесь. Я не могу сказать, что мое решение очень элегантное и, возможно, просто скрывает некоторый запах кода, поскольку я все еще изучаю TDD, но оно работает.

В своей работе я часто хочу войти в файл, указанный с помощью транспорта winston.transports.File(filename: "<filename>"). Допустим, мой файл журнала info.log

Конечно, во время тестирования я не хочу

  1. журналы, которые будут записаны в этот info.log
  2. 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, поскольку он вызывается только logger_utils.js.

Теперь я не совсем уверен в этом, но я думаю, что 2. определенный выше все еще не удался, несмотря на насмешки и глушение, потому что winston.createLogger() все еще вызывался, и я считаю, что это создаст файл, даже когда флаг --silent установлено. Я не знаю, правда ли это, но, тем не менее, приведенные выше решения не сработали.

Итак, (вдохновленный этим ответом) я решил просто не создавать объект winston при тестировании. Я сделал это, изменив файл 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 или npm run test:watch и т.д.)

Нам все еще нужно экспортировать что-то, чтобы logger_utils.js не сломался при тестировании, поэтому мы экспортируем пустой объект. Это хорошо, так как это будет издеваться.

Во всяком случае, это мой первый ответ на stackoverflow из пути. Я надеюсь, что это не было слишком пагубно, дайте мне знать, если кто-то хочет получить более подробную информацию.