How to suppress application logging messages from a node.js application when running unit tests?
node.jsUnit Testingmocha.jsnode.js Problem Overview
While unit-testing my node.js application (which is basically a REST backend) using mocha and supertest, I need only the test-specific message on the screen, but the stdout is also cluttered with application log messages.
I start the unit test with:
mocha -R spec .
... and get this output (this is what it should not be):
[App] Listening on port 3000 ...
[App] Starting app, hooray!
Project API
GET /projects
[App] entering "projects" module ...
√ should return an array of projects (317ms)
I marked the application log message with [App]. What I really want would be this output from the unit test:
Project API
GET /projects
√ should return an array of projects (317ms)
How can I suppress console.log/warn/error output by the application interspersed with Mocha's reporter output?
SOLUTION:
Following dankohn's approach, I ended up like this, which solves my issue (using [winston][1] for logging):
(in node's "main" server file, 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' })
]
});
}
... and to set the env variable, each unit test file starts with:
process.env.NODE_ENV = 'test';
[1]: http://github.com/flatiron/winston "winston"
node.js Solutions
Solution 1 - node.js
In your app.js:
if (process.env.NODE_ENV !== 'test') {
app.use(express.logger());
}
At the top of each of your mocha files:
process.env.NODE_ENV = 'test';
Update:
We use this function in our import code:
function logExceptOnTest(string) {
if (process.env.NODE_ENV !== 'test') {
console.log(string);
}
}
Then, replace all your console.log('it worked')
with logExceptOnTest('it worked')
. The basic trick is to use environment variables as a global flag as to the level of logging you want.
Solution 2 - node.js
Here's a pretty simple solution that uses SinonJS's test stubs to suppress all console.log/info/warn/error
statements before running your tests.
// 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
Solution 3 - node.js
Already answered but thought I would add that you can do this user 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});
}
Solution 4 - node.js
You can use mocha-suppress-logs
to hide logs generated by successuful tests but still keep the ones generated by failed tests to ease debugging.
Install:
npm install --save-dev mocha-suppress-logs
Then use it like this:
const suppressLogs = require('mocha-suppress-logs');
describe('Something', () => {
suppressLogs();
it('should do something', () => {
// test code
});
});
You can also do so globally for the entire test suite.
Here's a link to the module:
Solution 5 - node.js
Take a close look at the-log
. To hide logs you just need to activate silence mode once in some of your test script:
require('the-log').silent(); // That's all!!))
describe('Something', () => {
it('should do something', () => {
// test code
});
});
More about the-log
: https://github.com/ivanoff/the-log