I'm trying to unit test a simple piece of Express middleware, a cascading athenticator that checks first for a JWT token using a passport-jwt-strategy
, and then if that fails, using a passport-openid-strategy
. Each of the strategies is already well tested so what I am trying to test is their integration.
The module I am testing looks like this:
"use strict";
let passport = require('passport');
let Strategies = require('./strategies');
let setupDone = false;
// set up passport
let setup = function (app) {
passport.serializeUser(function (user, done) {
done(null, user);
});
passport.deserializeUser(function (obj, done) {
done(null, obj);
});
passport.use('jwt', Strategies.jwt);
passport.use('openid', Strategies.openId);
app.use(passport.initialize());
app.use(passport.session());
setupDone = true;
};
let authenticate = function (req, res, next) {
if (!setupDone) throw new Error('You must have run setup(app) before you can use the middleware');
console.log(' cascadingAuthentication');
// first try the token option
passport.authenticate('jwt', function (jwterr, user, info) {
console.log(' jwt auth', jwterr, user, info);
if (jwterr || !user) {
passport.authenticate('openid', function (oautherr, user, info) {
if (oautherr || !user) {
return next(oautherr);
} else {
next();
}
});
} else {
req.user = user;
next();
}
});
};
module.exports = {
setup: setup,
authenticate: authenticate
}
My Jasmine
test looks like this
"use strict";
let CascadingAuthentication = require('../../lib/middleware/cascadingAuthentication');
let TokenUtils = require('../support/tokenUtils');
let email = 'testing@test.tes';
describe('cascadingAuthentication', function () {
describe('when there is a token in the header', function () {
let req;
let res = {};
let app = {
use: function (used) { console.log('app.use called with', typeof used); }
};
beforeEach(function (done) {
let token = TokenUtils.makeJWT(email);
req = {
app: app,
header: {
Authorization: `Bearer ${token}`
}
}
CascadingAuthentication.setup(app);
CascadingAuthentication.authenticate(req, res, function () {
done();
});
});
it('populates req.user', function () {
expect(req.user).toEqual(jasmine.any(Object));
});
});
});
The issue I have is that, when I run the test, I see the first console.log(' cascadingAuthentication')
but I never see the second console.log('jwt auth', err, user, info)
. The code just dies inside passport.authenticate
without ever calling the callback, without raising an error, or without providing any kind of feedback at all.
I'm running my tests via gulp
using Jasmine
.
My questions are: in order,
- Can you see anything obvious that I have done that I might have just missed?
- Is there anything else I ought to mock out in my
req
,res
, orapp
that might make this test work? - Is there any way to debug this interactively; stepping through the code under test as it runs, rather than just adding
console.log
statements (which seems a little 1980s to me).