0

The function checks if the route is accessible or not

function isSessionCookieValid(req, res, next) {
      if (!isValid(req.session)) {
        return res.status(401).json({
          isLoggedIn: false
        });
      }
        return next();
 }

In another file I do a post request which is a protected route using the above function

  app
     .route('/url')
     .post(utils.isSessionCookieValid, (req, res, next) => {})

TESTING part

The problem is I don't know how to mock the isSessionCookieValid since it requires a next but am not able to pass the next callback in my test:

describe('testing routes', () => {
  it('should enter the route body', (done) => {
    utils.isSessionCookieValid(req, res, 'next should be here...');
    chai.request(server)
      .post('/url')
      .end(function (error, response, body) {
        if (error) {
          done(error);
        } else {
          done();
        }
      });
  });

});

ERROR: TypeError: next is not a function

EugenSunic
  • 13,162
  • 13
  • 64
  • 86
  • You need to mock the import of your `utils` modules. Not sure how you would do it in `chai`/`mocha`, but `jest` provides an easy way of mocking modules: https://jestjs.io/docs/en/mock-functions#mocking-modules – Cisco Jan 31 '19 at 16:07
  • 1
    [This](https://stackoverflow.com/questions/41995464/how-to-mock-middleware-in-express-to-skip-authentication-for-unit-test) might provide an idea for a solid solution. Anyway in this particular case, wouldn't it be simpler to mock the underlying `isValid` function? – Stock Overflaw Jan 31 '19 at 17:27
  • Why would you mock it? This is an API test so it should involve the database. – nicholaswmin Jan 31 '19 at 17:50

1 Answers1

1

I will use sinonjs as the mocking library. Mock the implementation of isSessionCookieValid middleware, let it always go to the next middleware.

E.g.

server.ts:

import express from 'express';
import * as utils from './utils';

const app = express();
const port = 3000;

app.route('/url').post(utils.isSessionCookieValid, (req, res, next) => {
  res.sendStatus(200);
});

if (require.main === module) {
  app.listen(port, () => {
    console.log(`Server is listening on port ${port}`);
  });
}

export { app };

utils.ts:

function isSessionCookieValid(req, res, next) {
  if (!isValid(req.session)) {
    return res.status(401).json({
      isLoggedIn: false,
    });
  }
  return next();
}

function isValid(session) {
  return true;
}

export { isSessionCookieValid };

server.test.ts:

import * as utils from './utils';
import sinon from 'sinon';
import chai, { expect } from 'chai';
import chaiHttp from 'chai-http';

chai.use(chaiHttp);

describe('testing routes', () => {
  it('should enter the route body', (done) => {
    const isSessionCookieValidStub = sinon.stub(utils, 'isSessionCookieValid').callsFake((req, res, next) => {
      next();
    });
    const { app } = require('./server');
    chai
      .request(app)
      .post('/url')
      .end((error, response) => {
        if (error) {
          return done(error);
        }
        sinon.assert.calledOnce(isSessionCookieValidStub);
        expect(response).to.have.status(200);
        done();
      });
  });
});

unit test result:

  testing routes
    ✓ should enter the route body (500ms)


  1 passing (510ms)

-----------|---------|----------|---------|---------|-------------------
File       | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s 
-----------|---------|----------|---------|---------|-------------------
All files  |      60 |       25 |      25 |      60 |                   
 server.ts |      80 |       50 |      50 |      80 | 12-13             
 utils.ts  |      20 |        0 |       0 |      20 | 2-11              
-----------|---------|----------|---------|---------|-------------------

source code: https://github.com/mrdulin/expressjs-research/tree/master/src/stackoverflow/54462600

Lin Du
  • 88,126
  • 95
  • 281
  • 483