BubbafrostXL
BubbafrostXL

Reputation: 21

How to mock req.session on Mocha/Chai API Unit Test

Using Mocha/Chai for REST API unit testing, I need to be able to mock req.session.someKey for a few of the end points. How can I go about mocking req.session?

I'm working on writing REST API unit tests for a NodeJS Express app that utilizes express-session. Some of these endpoints require the use of data stored in req.session.someKey, the endpoint is setup to return a 400 if req.session.someKey is undefined so I need to be able to mock it in order for the test to complete successfully.

Example code:

router.get('/api/fileSystems', utilities.apiAuth, (req, res) => {
  let customer = req.session.customer;
  let route = (customer === 'NONE') ? undefined : customer;

  if(route == undefined){
    res.status(400).send('Can't have customer of undefined');
  } else {
    let requestOptions = setRequestOptions(route);
    queryFileSystemInfo(requestOptions, (info) => {
      res.status(200).send(info);
    });

  }
});

What I've tried:

describe('/GET /api/fileSystems', () => {
  it('It should return information about the filesystem for a customer'), (done) => {
    chai.request(server)
      .get('api/fileSystems')
      .set('customer', '146')
      .end((err, res) => {
        res.should.have.status(200);
        done();
      });
  });
});

I attempted to use the .set() in order to set req.session but I believe that .set just sets the headers so I don't believe that I can update it that way unless I'm missing something.

Upvotes: 2

Views: 4469

Answers (3)

Mr5o1
Mr5o1

Reputation: 1828

In your express setup you usually plug in the session middleware like this

app.use(session(config))

instead you can put the session middleware in a handy accessible location, and make a wrapper for it, like this:

app.set('sessionMiddleware') = session(config)
app.use((...args) => app.get('sessionMiddleware')(...args)

Tests will need access to the express instance, you can do this by refactoring /app.js to export a function.

function app () {
  const app = express()
  // ... set up express
  return app
}

// run app if module called from cli like `node app.js`
if (require.main === module) instance = app()

module.exports = app

Then in your test, you can overwrite app.sessionMiddleware

describe('/GET /api/fileSystems', () => {
  it('It should return information about the filesystem for a customer'), (done) => {
    app.set('sessionMiddleware') = (req, res, next) => {
      req.session = mockSession // whatever you want here
      next()
    }
    chai.request(server)
      .get('api/fileSystems')
      .set('customer', '146')
      .end((err, res) => {
        res.should.have.status(200);
        done();
      });

    // then you can easily run assertions against your mock
    chai.assert.equal(mockSession.value, value)
  });
});

The other options I've seen on the net involve setting a cookie to match a session which is stored in the db, the problem with that approach is that you end up running into problems when the session in the db expires, so tests fail over time as fixtures become stale. With the approach outlined above you can work around that by setting expiries in the test.

Upvotes: 2

BubbafrostXL
BubbafrostXL

Reputation: 21

For this project, I ended up having to set req.session.customer in our server.js file that has an app.use() call that uses a middleware function to set the current session. I was unable to actually find a package that directly mutates the req.session object at test time.

Upvotes: 0

Muhammad Ali
Muhammad Ali

Reputation: 2014

mock-session is pretty use full to mock your session object

 let mockSession = require('mock-session');

 describe('/GET /api/fileSystems', () => {
  it('It should return information about the filesystem for a customer'), (done) => {
    let cookie = mockSession('my-session', 'my-secret', {"count":1});  // my-secret is you session secret key. 

    chai.request(server)
      .get('api/fileSystems')
      .set('cookie',[cookie])
      .end((err, res) => {
        res.should.have.status(200);
        done();
      });
  });
});

Upvotes: 1

Related Questions