Search code examples
node.jsexpressmocha.jschaichai-http

Test try catch with Mocha and Chai in Node + Express appp


I have nodeJS app with simple route as below:

const express = require('express')
const router = express.Router();
const logger = require('../logger');

router.use('/logMessage',(req, res)  => {
    try {
        logger.info(req.query.message);
        res.send({
            statusMessage: 'success'
        })
    } catch (err) {
        logger.error('error in logging');
        logger.error(err);
        res.send({
            statusMessage: 'failure'
        })
    }
});

module.exports = router;

I am able to successfully test the try block using below code, but how can I test the catch block ?

Test for try block:

describe('GET /logMessage', () => {
    it('should host logger api', (done) => {
        chai.request(server)
            .get('/logMessage?message=testMessage')
            .end((err, response) => {
                response.should.have.status(200);
                done();
            });
    });
});

Solution

  • You need to let the statement in the try block to throw an error. You can make this using sinonjs. For demonstration here, I will rewrite the implementation of console.info, when the message is "makeError", an error is thrown.

    E.g.

    router.js:

    const express = require('express');
    const router = express.Router();
    
    const logger = console;
    
    router.use('/logMessage', (req, res) => {
      try {
        logger.info(req.query.message);
        res.send({
          statusMessage: 'success',
        });
      } catch (err) {
        logger.error('error in logging');
        logger.error(err);
        res.send({
          statusMessage: 'failure',
        });
      }
    });
    
    module.exports = router;
    

    server.js:

    const express = require('express');
    const app = express();
    const router = require('./router');
    
    const port = 3000;
    app.use(router);
    
    if (require.main === module) {
      app.listen(port, () => console.log('server is listening on port:' + port));
    }
    
    module.exports = app;
    

    server.test.js:

    const server = require('./server');
    const chai = require('chai');
    const sinon = require('sinon');
    const chaiHttp = require('chai-http');
    chai.use(chaiHttp);
    chai.should();
    
    describe('62080151', () => {
      describe('GET /logMessage', () => {
        it('should host logger api', (done) => {
          chai
            .request(server)
            .get('/logMessage?message=testMessage')
            .end((err, response) => {
              response.should.have.status(200);
              done();
            });
        });
    
        it('should handle error', (done) => {
          sinon.stub(console, 'info').callsFake((message) => {
            if (message === 'makeError') {
              throw new Error('custom error');
            }
          });
          sinon.spy(console, 'error');
          chai
            .request(server)
            .get('/logMessage?message=makeError')
            .end((err, response) => {
              response.should.have.status(200);
              sinon.assert.match(console.error.firstCall.calledWithExactly('error in logging'), true);
              console.error.secondCall.args[0].should.be.instanceOf(Error);
              done();
            });
        });
      });
    });
    

    integration test results with coverage report:

      62080151
        GET /logMessage
    testMessage
          ✓ should host logger api
    error in logging
    Error: custom error
        at Console.sinon.stub.callsFake (/Users/ldu020/workspace/github.com/mrdulin/expressjs-research/src/stackoverflow/62080151/server.test.js:23:17)
        at Object.invoke (/Users/ldu020/workspace/github.com/mrdulin/expressjs-research/node_modules/sinon/lib/sinon/behavior.js:163:32)
        at Console.functionStub (/Users/ldu020/workspace/github.com/mrdulin/expressjs-research/node_modules/sinon/lib/sinon/stub.js:39:43)
        at Function.invoke (/Users/ldu020/workspace/github.com/mrdulin/expressjs-research/node_modules/sinon/lib/sinon/proxy-invoke.js:47:47)
        at Console.bound consoleCall [as info] (/Users/ldu020/workspace/github.com/mrdulin/expressjs-research/node_modules/sinon/lib/sinon/proxy.js:214:26)
        at router.use (/Users/ldu020/workspace/github.com/mrdulin/expressjs-research/src/stackoverflow/62080151/router.js:1:1894)
        at Layer.handle [as handle_request] (/Users/ldu020/workspace/github.com/mrdulin/expressjs-research/node_modules/express/lib/router/layer.js:95:5)
        at trim_prefix (/Users/ldu020/workspace/github.com/mrdulin/expressjs-research/node_modules/express/lib/router/index.js:317:13)
        at /Users/ldu020/workspace/github.com/mrdulin/expressjs-research/node_modules/express/lib/router/index.js:284:7
        at Function.process_params (/Users/ldu020/workspace/github.com/mrdulin/expressjs-research/node_modules/express/lib/router/index.js:335:12)
        at next (/Users/ldu020/workspace/github.com/mrdulin/expressjs-research/node_modules/express/lib/router/index.js:275:10)
        at Function.handle (/Users/ldu020/workspace/github.com/mrdulin/expressjs-research/node_modules/express/lib/router/index.js:174:3)
        at router (/Users/ldu020/workspace/github.com/mrdulin/expressjs-research/node_modules/express/lib/router/index.js:47:12)
        at Layer.handle [as handle_request] (/Users/ldu020/workspace/github.com/mrdulin/expressjs-research/node_modules/express/lib/router/layer.js:95:5)
        at trim_prefix (/Users/ldu020/workspace/github.com/mrdulin/expressjs-research/node_modules/express/lib/router/index.js:317:13)
        at /Users/ldu020/workspace/github.com/mrdulin/expressjs-research/node_modules/express/lib/router/index.js:284:7
        at Function.process_params (/Users/ldu020/workspace/github.com/mrdulin/expressjs-research/node_modules/express/lib/router/index.js:335:12)
        at next (/Users/ldu020/workspace/github.com/mrdulin/expressjs-research/node_modules/express/lib/router/index.js:275:10)
        at expressInit (/Users/ldu020/workspace/github.com/mrdulin/expressjs-research/node_modules/express/lib/middleware/init.js:40:5)
        at Layer.handle [as handle_request] (/Users/ldu020/workspace/github.com/mrdulin/expressjs-research/node_modules/express/lib/router/layer.js:95:5)
        at trim_prefix (/Users/ldu020/workspace/github.com/mrdulin/expressjs-research/node_modules/express/lib/router/index.js:317:13)
        at /Users/ldu020/workspace/github.com/mrdulin/expressjs-research/node_modules/express/lib/router/index.js:284:7
        at Function.process_params (/Users/ldu020/workspace/github.com/mrdulin/expressjs-research/node_modules/express/lib/router/index.js:335:12)
        at next (/Users/ldu020/workspace/github.com/mrdulin/expressjs-research/node_modules/express/lib/router/index.js:275:10)
        at query (/Users/ldu020/workspace/github.com/mrdulin/expressjs-research/node_modules/express/lib/middleware/query.js:45:5)
        at Layer.handle [as handle_request] (/Users/ldu020/workspace/github.com/mrdulin/expressjs-research/node_modules/express/lib/router/layer.js:95:5)
        at trim_prefix (/Users/ldu020/workspace/github.com/mrdulin/expressjs-research/node_modules/express/lib/router/index.js:317:13)
        at /Users/ldu020/workspace/github.com/mrdulin/expressjs-research/node_modules/express/lib/router/index.js:284:7
        at Function.process_params (/Users/ldu020/workspace/github.com/mrdulin/expressjs-research/node_modules/express/lib/router/index.js:335:12)
        at next (/Users/ldu020/workspace/github.com/mrdulin/expressjs-research/node_modules/express/lib/router/index.js:275:10)
        at Function.handle (/Users/ldu020/workspace/github.com/mrdulin/expressjs-research/node_modules/express/lib/router/index.js:174:3)
        at Function.handle (/Users/ldu020/workspace/github.com/mrdulin/expressjs-research/node_modules/express/lib/application.js:174:10)
        at Server.app (/Users/ldu020/workspace/github.com/mrdulin/expressjs-research/node_modules/express/lib/express.js:39:9)
        at Server.emit (events.js:198:13)
        at parserOnIncoming (_http_server.js:677:12)
        at HTTPParser.parserOnHeadersComplete (_http_common.js:109:17)
          ✓ should handle error (43ms)
    
    
      2 passing (81ms)
    
    -----------|---------|----------|---------|---------|-------------------
    File       | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s 
    -----------|---------|----------|---------|---------|-------------------
    All files  |      90 |       50 |      50 |   94.74 |                   
     router.js |     100 |      100 |     100 |     100 |                   
     server.js |   77.78 |       50 |       0 |    87.5 | 9                 
    -----------|---------|----------|---------|---------|-------------------