2015-11-10 7 views
1

Я пытаюсь выполнить тестирование простого кусочка промежуточного программного обеспечения Express, каскадного атеистатора, который сначала проверяет токен JWT, используя passport-jwt-strategy, а затем, если это не удается, используя passport-openid-strategy. Каждая из стратегий уже хорошо протестирована, поэтому я пытаюсь проверить их интеграцию.Тестирование Express/Passport промежуточного программного обеспечения с использованием Jasmine - passport.authenticate никогда не завершается

Модуль Я тестирование выглядит так:

"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 
} 

Мой Jasmine тест выглядит следующим образом

"use strict"; 

let CascadingAuthentication = require('../../lib/middleware/cascadingAuthentication'); 
let TokenUtils = require('../support/tokenUtils'); 
let email = '[email protected]; 

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)); 
    }); 
    }); 

}); 

Проблема у меня есть, что, когда я запустить тест, я вижу первый console.log(' cascadingAuthentication'), но я никогда не вижу второго console.log('jwt auth', err, user, info). Код просто умирает внутри passport.authenticate, не вызывая обратного вызова, не поднимая ошибки или вообще не предоставляя никакой обратной связи.

Я выполняю свои тесты через gulp с использованием Jasmine.

Мои вопросы: для того,

  1. Вы можете увидеть что-нибудь очевидное, что я сделал, что я мог бы просто пропустил?
  2. Есть ли что-нибудь еще, что я должен высмеивать в своих req, res или app, которые могут заставить эту тестовую работу работать?
  3. Есть ли способ отлаживать это в интерактивном режиме; переходя через тестируемый код, когда он запускается, вместо того, чтобы просто добавлять console.log заявления (которые кажутся мне немного 1980-х годов).

ответ

0

Копаем через источник passport Я разработал две проблемы с моим кодом.

Во-первых, passport.authenticate возвращает функцию промежуточного программного обеспечения, она фактически не выполняет эту функцию. Таким образом, решение было просто вызвать возвращенную функцию.

Так что мой метод Аутентифицировать теперь выглядит следующим образом:

let authenticate = function(req, res, next) { 
    if (!setupDone) throw new Error('You must have run setup(app) before you can use the middleware'); 
    // first try the token option 
    passport.authenticate('jwt', function(jwterr, user, info) { 
    if (jwterr || !user) { 
     passport.authenticate('openid', function(autherr, user, info) { 
     if (autherr || !user) { 
      return next(autherr); 
     } else { 
      next(); 
     } 
     })(req, res, next); 
    } else { 
     req.user = user; 
     next(); 
    } 
    })(req, res, next); 
}; 

(В приведенном выше примере обрезается для использования в вопросе)

Другой вопрос в моем тесте я использовал header вместо headers в моей mock req объект, а также authorization должен был иметь нижний регистр a.

С этими двумя исправлениями тест проходит.

0

Я довольно долго искал это и, в конце концов, приземлился на следующую настройку (чтобы проверить passport.authenticate('local',() => {})).

auth-router.JS

const express = require('express'); 
 
const passport = require('passport'); 
 

 
const login = (req, res, next) => { 
 
    passport.authenticate('local', (err, user, info) => { 
 
    if (err) { 
 
     next(err); 
 
     return; 
 
    } 
 

 
    if (!user) { 
 
     const error = new Error(info.message); 
 
     error.status = 404; 
 
     next(error); 
 
     return; 
 
    } 
 

 
    // Add the found user record to the request to 
 
    // allow other middlewares to access it. 
 
    req.user = user; 
 
    next(); 
 
    })(req, res, next); 
 
}; 
 

 
const router = express.Router(); 
 
router.post('/auth/login', login); 
 

 
module.exports = { 
 
    login, 
 
    router 
 
};

Auth-router.spec.js

const passport = require('passport'); 
 

 
describe('login',() => { 
 
    it('should login and add the user to the request object', (done) => { 
 
    spyOn(passport, 'authenticate').and.callFake((strategy, callback) => { 
 
     const err = null; 
 
     const user = {}; 
 
     const info = {}; 
 
     callback(err, user, info); 
 
     return (req, res, next) => {}; 
 
    }); 
 

 
    const auth = require('./auth'); // my middleware function 
 
    const req = { body: {} }; 
 
    const res = {}; 
 
    const next =() => { 
 
     expect(req.user).toBeDefined(); 
 
     done(); 
 
    }; 
 

 
    auth.login(req, res, next); 
 
    }); 
 
});