Skip to content

Instantly share code, notes, and snippets.

@WaleedAshraf
Last active March 21, 2023 08:42
Show Gist options
  • Save WaleedAshraf/4106be954bf522cf25bda3b59e2ea8a6 to your computer and use it in GitHub Desktop.
Save WaleedAshraf/4106be954bf522cf25bda3b59e2ea8a6 to your computer and use it in GitHub Desktop.
Mocking Express Session For Tests

How to mock express session?

sinon is being used to mock methods in tests. It is one of the most used package for testing. But Is there a way to mock session objects in tests for express?

I'm working on a project where I upload images to s3 in bulk (albums) and than further apply some processing like resizing/compression/editing on them.

It's a express app with middlewares for authorization, authentication, setting context and is working fine. Recently I started adding testcases for different routes using mocha. I'm using cookie-session for session handling in app.

For one route, I needed to mock req.session object. (Need to set it's value before calling the other route.) I have two routes, one is to upload photo to s3 (create) and second one (submit) to apply further processing on uploaded images.

First route (create) set req.session value and redirect to second one (submit).

1) api/image/create

exports.create = function(req, res) {
  // upload image to s3
  var photos = PhotosTable.create(req.files.names); // add entries in database
  req.session.count = photos.length; // set count in req.session
  res.redirect(`api/image/submit`);
}

2) api/image/submit (need to add testcase for this one)

exports.submit = function(req, res) {
  if (req.session.count && req.session.count > 0) { // get count from req.session
    // perform further tasks
    res.sendStatus(200); 
  } else {
    res.sendStatus(400); 
  }
}

I just want to test second route (api/image/submit).

Issue is that api/image/submit route checks for req.session.count and than perform further tasks, if count is not set, it sends 400 in reponse. With mocha you can only check response from one route, can't wait for result from redirect call.

One easy solution is that I send a req param from testcase, and check it in method if that param is present, than skip checking for req.session.count. Duh! This seems dumbest solution.

I could also easily get rid of second route and add all logic in one. But should I ? As far as I know, one should never change implementation for sake of testcases. As this problem seemes so common but I couldn't find any solution on internet (I mnea stackoverflow :D). My first guess was that there would be some npm-package to handle this kind of situation. As mocha, cookie-session are one the most modules modules with express.

Alas! There isn't any.

I'm using cookie-session with express to maintain sessions:

cookie-session maintains the session by keeping signed cookies. It uses cookies with Keygrip and Crypto to set and validate session keys.

It requires a name and a key for setting session cookies. name is used as cookie name. key is used to sign cookie value using Keygrip

So, somehow I should set req.session.count value in testcase, before calling the route.


// name = "my-session" ->  base64 value of required object (cookie)
// name.sig = "my-session.sig" -> signed value of cookie using Keygrip

let cookie = Buffer.from(JSON.stringify({"count":2})).toString('base64'); // base64 converted value of cookie

let kg = Keygrip(['testKey']) // same key as I'm using in my app
let hash = kg.sign('my-sessssion=' + cookie);

await request(app).get('api/image/submit').set("Accept", "text/html")
    .set('cookie', ['my-session=' + cookie + '; ' + 'my-session.sig=' + hash + ';'])
    .expect(200);

That's it. By setting this cookie in request, I was able to set req.session.count to my desired value. Hah!! xD

exports.submit = function(req, res) {         
  if(req.session.count && req.session.count > 0) { // true                      
    //do something                
    res.sendStatus(200);                    
  }
}

This is just one use-case for mocking session in express, but it can be used wherever you need to set req.session with any value.

I have also created package at npm: mock-session https://www.npmjs.com/package/mock-session

@AnisBelahcene
Copy link

hello i want to ask you if it works with jest ?

@WaleedAshraf
Copy link
Author

@AnisBelahcene It should work. Though I haven't tested it.

@AnisBelahcene
Copy link

i am using express-session i have to switch to cookie-session first, i will try thank you

@snowman1120
Copy link

snowman1120 commented Jan 13, 2023

It doesn't work. How can I do it?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment