How to suppress application logging messages from a node.js application when running unit tests?

node.jsUnit Testingmocha.js

node.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:

https://www.npmjs.com/package/mocha-suppress-logs

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

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionandimeierView Question on Stackoverflow
Solution 1 - node.jsDan KohnView Answer on Stackoverflow
Solution 2 - node.jsDerek SoikeView Answer on Stackoverflow
Solution 3 - node.jsJustin HamadeView Answer on Stackoverflow
Solution 4 - node.jsAleGView Answer on Stackoverflow
Solution 5 - node.jsDimitry IvanovView Answer on Stackoverflow