我意识到这已经很晚了,但我只是想用 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,因为它只被logger_utils.js调用。
现在,我对此并不完全确定,但我认为上面定义的 2. 尽管有模拟和静音,但仍然失败,因为 winston.createLogger() 仍在被调用,我相信即使在 - -silent 标志已设置。我不知道这是不是真的,但是上面的解决方案不起作用。
所以,(受this answer 启发)我决定做的只是在测试时不创建任何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 的第一个回答。我希望这不会太灾难性,如果有人想了解更多细节,请告诉我。