How to mock middleware in Express to skip authentication for unit test?
Asked Answered
A

1

46

I have the following in Express

 //index.js

 var service = require('./subscription.service');
 var auth = require('../auth/auth.service');
 var router = express.Router();

 router.post('/sync', auth.isAuthenticated, service.synchronise);

 module.exports = router;

I want to override or mock isAuthenticated to return this

auth.isAuthenticated = function(req, res, next) { 
  return next(); 
}

Here is my unit test:

it('it should return a 200 response', function(done) {

  //proxyquire here?

  request(app).post('/subscriptions/sync')
  .set('Authorization','Bearer '+ authToken)
  .send({receipt: newSubscriptionReceipt })
  .expect(200,done);
});

I have tried mocking index.js using proxyquire - I think I need to stub the router? I have also tried to override in the test

app.use('/subscriptions', require('./api/subscription'));

There must be a simple way to mock this out so I don't need to authenticate the request. Any ideas?

Avelinaaveline answered 2/2, 2017 at 6:21 Comment(0)
M
37

You can use sinon to stub isAuthenticated method, but you should do that before a reference to auth.isAuthenticated is set as a middleware, so before you require the index.js and app is created. Most likely you would want this in a beforeEach hook:

var app;
var auth;

beforeEach(function() {
  auth = require('../wherever/auth/auth.service');
  sinon.stub(auth, 'isAuthenticated')
      .callsFake(function(req, res, next) {
          return next();
      });

  // after you can create app:
  app = require('../../wherever/index');
});

afterEach(function() {
  // restore original method
  auth.isAuthenticated.restore();
});

it('it should return a 200 response', function(done) {
  request(app).post('/subscriptions/sync')
  .set('Authorization','Bearer '+ authToken)
  .send({receipt: newSubscriptionReceipt })
  .expect(200,done);
});

Please note that even after auth.isAuthenticated is restored, existing app instance will have stub as a middleware, so you need to create another app instance if you need to get an original behavior by some reason.

Update: there is a way to alter middleware's behavior without recreating the server each time as explained in another SO answer.

Malatya answered 2/2, 2017 at 8:24 Comment(6)
I'm running into a similar problem, and it feels like this solution should work for me, but mine is still broken. Any thoughts on this similar problem? #53853373Belamy
@LukeSchlangen posted an answer thereMalatya
@SergeyLapin Is there any way to mock parameterized middleware using Sinon? middleware definition like as: exports.authUser = function (options) { return function (req, res, next) { // Implement the middleware function based on the options object next() } }Preventer
@hareshhanat sure, I believe just the same way, just need to return middleware instead of passing it to callsFake: sinon.stub(authModule, 'authUser') .callsFake((options) => (req, res, next) => { return next(); });Malatya
@SergeyLapin Yes, got it. Thank you so much!!Preventer
I implemented in the next way with Typescript if anyone looking for something similar https://mcmap.net/q/373781/-simple-way-to-test-middleware-in-express-without-creating-recreating-serverCountersignature

© 2022 - 2024 — McMap. All rights reserved.