在摩卡testing过程中将stdout和stderr静音

我会通过承认我可能正在做一些我不应该做的事情来做序。 但是既然我已经深深的了解了,我也可以理解为什么事情会这样发生。

我正在使用摩卡来testing一些Node.js代码。 此代码使用Winston日志库,它直接调用process.stdout.write()process.stderr.write() ( source )。 它运作良好; 我对这种行为没有抱怨。

但是,当我对这段代码进行unit testing的时候,Mochatesting运行器的输出偶尔会穿插一些日志输出行,这在一些记者( dotbdd )中是丑陋的,而在其他记者( bdd )中是彻头彻尾的无效的。 我想在不修改或inheritanceWinston的情况下阻止这个输出,而且我想避免修改应用程序本身,如果我可以避免的话。

我到达的是一组实用函数,它们可以用一个无操作函数暂时replaceNode的内build函数,反之亦然:

 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; } 

在各种testing规范中,我直接在产生不需要的输出的任何调用或断言之前调用了mute() ,并在之后直接unmute() 。 这感觉有点不好意思,但是工作起来 – 运行testing时,在控制台上没有出现单字节不需要的输出。

现在变得奇怪了!

我第一次尝试将输出redirect到一个文件:

 mocha spec_file.js > output.txt 

不想要的输出回来了! 发送到stdout的每个输出都出现在文件中。 添加2>&1 ,我也得到stderr文件。 不pipe怎样,控制台上都没有显示任何内容。

为什么testing代码在两次调用之间performance得如此不同? 我的直觉是,摩卡正在做一些testing,以确定它是否写入TTY,但我无法find一个显而易见的地方,它改变了它的写入行为。

还有更广泛的问题,在testing期间是否有任何正确的方法来静音stdout / stderr,而不是将所有潜在的日志logging应用程序代码包含在检查testing环境的条件中?

请参阅https://www.npmjs.org/package/mute

 it('should shut the heck up', function (done) { var unmute = mute() app.options.defaults = true; app.run(function() { unmute(); helpers.assertFiles([ ['package.json', /"name": "temp-directory"/], ['README.md', /# TEMP.Directory/] ]); done(); }); }); 

我发现这种行为的可能原因。 这确实与stdout / stderr是否是TTY有关。

当脚本在控制台中运行时,这些都是TTY,并且process.stdoutprocess.stderr似乎是tty.WriteStream实例,而不是像我最初设想的那样是stream.Writable 。 就我的相互作用而言,这两个类实际上并没有什么不同 – 它们都有公用的write()方法,这些方法调用了内部_write()方法,并且都共享相同的方法签名。

当传送到一个文件,事情有一点点不同。 process.stdoutprocess.stderr是不是很熟悉的不同类的实例。 最好的我可以认为,这是一个fs. SyncWriteStream fs. SyncWriteStream ,但这是在黑暗中刺。 无论如何,这个类没有_write()方法,所以试图覆盖它是毫无意义的。

解决的办法是移动一个级别,并用write()而不是_write()静音。 它做同样的事情,而且不pipe输出到哪里都一致。