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

35,321

Solution 1

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

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

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

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

Share:
35,321
andimeier
Author by

andimeier

Updated on February 20, 2022

Comments

  • andimeier
    andimeier over 2 years

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