运行单元测试时如何抑制来自 node.js 应用程序的应用程序日志消息?
Posted
技术标签:
【中文标题】运行单元测试时如何抑制来自 node.js 应用程序的应用程序日志消息?【英文标题】:How to suppress application logging messages from a node.js application when running unit tests? 【发布时间】:2014-05-07 17:46:46 【问题描述】:在使用 mocha 和 supertest 对我的 node.js 应用程序(基本上是一个 REST 后端)进行单元测试时,我只需要屏幕上的特定于测试的消息,但标准输出中也充满了应用程序日志消息。
我开始单元测试:
mocha -R spec .
... 并得到这个输出(这是它不应该的):
[App] Listening on port 3000 ...
[App] Starting app, hooray!
Project API
GET /projects
[App] entering "projects" module ...
√ should return an array of projects (317ms)
我用 [App] 标记了应用程序日志消息。我真正想要的是单元测试的输出:
Project API
GET /projects
√ should return an array of projects (317ms)
如何抑制应用程序的console.log/warn/error 输出,其中穿插着Mocha 的报告器输出?
解决方案:
按照 dankohn 的方法,我最终得到了这样的结果,这解决了我的问题(使用 winston 进行日志记录):
(在节点的“主”服务器文件 server.js 中:)
if (process.env.NODE_ENV !== 'test')
logger = new (winston.Logger)(
transports: [
new (winston.transports.Console)(),
new (winston.transports.File)( filename: 'foo.log' )
]
);
else
// while testing, log only to file, leaving stdout free for unit test status messages
logger = new (winston.Logger)(
transports: [
new (winston.transports.File)( filename: 'foo.log' )
]
);
...并设置环境变量,每个单元测试文件都以:
process.env.NODE_ENV = 'test';
【问题讨论】:
嗨,我遇到了一些问题,我使用了类似的方法来修复它,但我仍然在控制台中遇到猫鼬错误。你知道怎么处理吗? 【参考方案1】:在您的 app.js 中:
if (process.env.NODE_ENV !== 'test')
app.use(express.logger());
在每个 mocha 文件的顶部:
process.env.NODE_ENV = 'test';
更新:
我们在导入代码中使用这个函数:
function logExceptOnTest(string)
if (process.env.NODE_ENV !== 'test')
console.log(string);
然后,将您的所有console.log('it worked')
替换为logExceptOnTest('it worked')
。基本技巧是使用环境变量作为你想要的日志级别的全局标志。
【讨论】:
哎呀——你猜对了,我使用的是 Express。感谢您及时的回复。我不能按原样使用您的解决方案,因为 express.logger() AFAIU 仅记录请求/响应,但不能用于应用程序日志记录(调试消息等)。但是从您的想法中提取本质,要走的路似乎是:(1)摆脱console.log(我目前正在使用)(2)改用可配置的日志框架(3)基于NODE_ENV env配置日志工具环境。现在我必须弄脏(2)和(3)...... 查看我的更新。如果您想要更多的日志记录功能,请参阅github.com/flatiron/winston,但我们还不需要它。 我确实希望在单元测试时记录消息,因为在编写单元测试时(提前),我仍然想看看应用程序的底层发生了什么。因此,我将采用您建议的改编版本:使用 winston 配置日志记录设施并使用 env 变量(如您建议的那样)来区分“测试”和“非测试”模式。在“测试”模式下,将应用程序消息记录到指定文件(保持单元测试输出干净) - 在“非测试”模式(= 生产模式)下,将应用程序消息记录到标准输出,通过管道传输到例如永远。 感谢您的帮助!我最终使用了 rlogger,只是将日志级别包装在检查环境变量中的“测试”字符串的周围。即仅在测试期间记录错误,否则在正常操作期间全部记录。【参考方案2】:这是一个非常简单的解决方案,它使用SinonJS 的test stubs 在运行测试之前抑制所有console.log/info/warn/error
语句。
// my-method.js
export function myMethod()
console.log(`I'm about to return true`)
return true
// my-method.test.js
import describe, it, before from 'mocha'
import chai from 'chai'
import sinon from 'sinon'
import chalk from 'chalk'
import myMethod from './my-method.js'
const expect = chai.expect
describe(chalk.underline('My Test Group'), () =>
before(() =>
sinon.stub(console, 'log') // disable console.log
sinon.stub(console, 'info') // disable console.info
sinon.stub(console, 'warn') // disable console.warn
sinon.stub(console, 'error') // disable console.error
)
describe('myMethod', () =>
it('should return true', () =>
expect(myMethod()).to.be.true // without printing to the console
)
)
)
// output
My Test Group
myMethod
✓ should return true
【讨论】:
这看起来像我想要的方法,但我无法让它发挥作用。我已经在使用 sinon,那些stub
调用应该是所有需要的,对吧?
有时我需要将 stub/restore 放入测试本身以使其正常工作
这是正确的方法..应该被接受为解决方案!【参考方案3】:
已经回答但我想我会补充说你可以做这个用户winston.add()
var logger = new (winston.Logger)(
transports: [
new (winston.transports.File)(filename: 'node.log')
]
);
if (process.env.NODE_ENV === 'test')
logger.add(winston.transports.Console, prettyPrint: true);
【讨论】:
【参考方案4】:您可以使用mocha-suppress-logs
隐藏成功测试生成的日志,但仍保留失败测试生成的日志以方便调试。
安装:
npm install --save-dev mocha-suppress-logs
然后像这样使用它:
const suppressLogs = require('mocha-suppress-logs');
describe('Something', () =>
suppressLogs();
it('should do something', () =>
// test code
);
);
您也可以对整个测试套件全局执行此操作。
这是模块的链接:
https://www.npmjs.com/package/mocha-suppress-logs
【讨论】:
以上是关于运行单元测试时如何抑制来自 node.js 应用程序的应用程序日志消息?的主要内容,如果未能解决你的问题,请参考以下文章
使用带有事务的内存数据库进行单元测试时,如何抑制 InMemoryEventId.TransactionIgnoredWarning?
UICollectionView,来自注册为单元格的框架目标的 nib 在运行时失败
运行 Mongoose 时执行 ajax 调用时如何处理 Node.js 发现