【发布时间】:2014-09-13 14:17:51
【问题描述】:
我首先要承认我可能正在做一些我不应该做的事情。不过既然我已经这么深了,那我也应该明白为什么会这样了。
我正在使用 Mocha 测试一些 Node.js 代码。此代码使用 Winston 日志库,该库直接调用 process.stdout.write() 和 process.stderr.write() (source)。它运作良好;我对这种行为没有任何抱怨。
但是,当我对这段代码进行单元测试时,Mocha 测试运行器的输出偶尔会穿插日志输出行,这在某些记者(dot、bdd)和其他人( xunit)。我想在不修改或继承 Winston 的情况下阻止此输出,并且如果可以避免的话,我想避免修改应用程序本身。
我得到的是一组实用函数,可以暂时用无操作函数替换 Node 内置函数,反之亦然:
var stdout_write = process.stdout._write,
stderr_write = process.stderr._write;
function mute() {
process.stderr._write = process.stdout._write = function(chunk, encoding, callback) {
callback();
};
}
function unmute() {
process.stdout._write = stdout_write;
process.stderr._write = stderr_write;
}
在各种测试规范中,我在任何产生不需要的输出的调用或断言之前直接调用了mute(),之后直接调用了unmute()。感觉有点 hacky,但它确实有效——运行测试时,控制台上没有出现一个字节的不需要的输出。
现在变得奇怪了!
我第一次尝试将输出重定向到文件:
mocha spec_file.js > output.txt
不需要的输出又回来了!发送到标准输出的每一条输出都出现在文件中。添加2>&1,我也得到了文件中的stderr。不过,无论哪种情况,控制台上都不会出现任何内容。
为什么两个调用之间的测试代码表现如此不同?我的直觉猜测是 Mocha 正在做某种测试以确定它是否正在写入 TTY,但我无法发现它改变写入行为的明显地方。
还有一个更广泛的问题,是否有任何正确方法可以在测试期间静音 stdout/stderr,而无需将所有可能记录日志的应用程序代码包装在检查测试环境的条件中?
【问题讨论】:
-
不知道 Winston,但有可能它会检查 stdout 和 stderr 是否是 tty,如果是,则行为不同(例如:登录颜色等)?如果是这样,我想不要覆盖
write和_write,而是创建一个“空”流并完全替换stdout和stderr。如果没有让温斯顿这样做的“全局设置”,我也会感到惊讶:静音。 (例如:将日志级别降至最低)。
标签: node.js unit-testing stdout mocha.js stderr