Are you using an Express app and need to add integration (end-to-end) testing? Here’s what I discovered when I was trying to do this for a project that I worked on. This article covers the background around the challenge that I faced when trying to add an integration test for an Express App, and a simple way to solve this.
Hopefully, this helps those that might be facing the same problem.
I was tasked with working on a project where I was uploading images to amazon s3 in bulk (albums) and then needed to apply some processing like resizing/compression/editing on them.
It is an Express app with middleware for authorization, authentication, setting context and is working fine. Recently, however, I started adding test cases for different routes using mocha. I’m using cookie-session for session handling in the app, which means cookie-session is responsible for encrypting/setting/decrypting all session related data.
Here’s where the challenge initial started for me. I have two routes: one is to upload the photo to s3 (create) and the second one (submit) to apply further processing on uploaded images. For one route, I needed to mock
req.session object. I needed to set its value before calling the other route. First route (create) set
req.session value and redirect to the second one (submit).
2) api/image/submit (need to add a test case for this one)
I just want to test second route (
api/image/submit). The issue is that
api/image/submit route checks for
req.session.count and than perform further tasks. If the count is not set, it sends 400 in response. With mocha you can only check response from one route, you can’t wait for the result from redirect call.
Fixes that Seem Smart, but Pose More Challenges
The easy solution to fix this issue is to send a req-param from the test case, and check it in method if that param is present, then skip checking for req.session.count.
However, this solution isn’t the best because:
- It can’t be reused as it’s not a generic solution.
- Adding if/else for an extra parameter in controller logic will require more checks to verify that controller logic is not affected.
I could also easily get rid of the second route and add all logic in one. But should I? As far as I know,
one should never change implementation for the sake of test cases.
This problem seems so common but I couldn’t find any solution on the internet (or at least StackOverflow). My first guess was that there would be some npm-package to handle this kind of situation. As mocha, cookie-session are the most used modules with Express.
Alas! There isn’t any.
How I Eventually Solved This Issue
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.
I thought that I could fix this by setting req.session.count value in the test case, before calling the route. Here’s the code:
That’s it. By setting this cookie in the request, I was able to set req.session.count to my desired value.
This is just one use case for mocking session in Express. Most of the time tests require customized values for the assertion, but it can be used wherever you need to set req.session with any specific value.
I have also created a package at npm: mock-session to make it easier for you. Please let me know if it works!