如何单位测试护照本地策略? (sinon,代理)

时间:2016-07-29 00:06:25

标签: express passport.js sinon passport-local

我的本​​地登录策略中有一些逻辑用于护照我想用stubs / mocks进行单元测试(因为它调用外部API),但我似乎无法进入函数来测试它。

这是我的test.js文件:

var expect = require('chai').expect;
var sinon = require('sinon');
var proxyquire = require('proxyquire');
require('../config/passport.js');

describe('it should get user account from the API', function () {
    it('should be able to access passport authenticate', function(){
        var reqUserObject = {
            body: { user_name: 'fakeymcfakeypants', password: '123Skidoo' }
        }
        var requestPromiseStub = sinon.stub();

        requestPromiseStub.onCall(0).returns(Promise.resolve('{"userId": 138}'))
                .onCall(1).returns(Promise.resolve('{"userName": "fakeymcfakeypants", "status": 0}'))

        var passportTest = proxyquire('passport', {
            'request-promise': requestPromiseStub
          });

        var passportStub = sinon.stub(passportTest, "authenticate");

        var response = passportStub.calledWith('localLogin', reqUserObject);
        console.log(response);
        expect.response.to.be.true;


     });

    });

config / passport.js中的功能设置:

var rp = require('request-promise');
var passport = require("passport");
var LocalStrategy = require('passport-local').Strategy;


module.exports = function (passport, LocalStrategy) {

  passport.use('localLogin', new LocalStrategy({
        usernameField : 'user[user_name]',
        passwordField : 'user[password]'},
    function(username, password, done) {
      //logic blah blah blah here, uses two request-promise calls
      return done(null, username);
    })
  )
 }

据我所知,没有调用passport.authenticate方法(它总是返回false)。如果我删除proxyquire并且只需要护照& config / passport.js'通常'反应也是错误的。

我知道这有点复杂,所以关于如何测试这个的任何其他建议将不胜感激!

编辑添加当前代码:

var expect = require('chai').expect;
var chai = require('chai');
var sinon = require('sinon');
var proxyquire = require('proxyquire');
var passport = require('passport');
var sinonChai = require('sinon-chai');
var async = require('async');

chai.use(sinonChai);

describe('canary test: passport', function (){
        it('should pass this canary test', function(){
            expect(true).to.be.true;
        });
    });

describe('it should get user account from the API', function () {
    var authSpy;
    var requestPromiseStub;
    var passportResponse;
    var userResponse;

    beforeEach(function () {  
      this.sandbox = sinon.sandbox.create()
      authSpy = sinon.spy(passport, 'authenticate');

    })

    afterEach(function () {  
      this.sandbox.restore()
    })


    it('should be able to access passport authenticate', function(){    
        var mockReq = {
              body: {
                username: 'fakeymcfakeypants',
                password: '123Skidoo'
              },
            logIn: function () {}
            };

        var mockRes = {
            };

        requestPromiseStub = sinon.stub();

        next = sinon.stub();

        requestPromiseStub.onCall(0).returns(Promise.resolve({userId: 138, statusCode: 200}))
                .onCall(1).returns(Promise.resolve({userName: 'fakeymcfakeypants', status : 0}))

        var overrides = {
          'request-promise': requestPromiseStub,
          'authenticate': {authenticate: authSpy}
        };

        proxyquire('../config/passport.js', overrides)();

        //added 'next' here as authenticate expects it: https://github.com/jaredhanson/passport/blob/master/lib/middleware/authenticate.js#L81
        //passport should return either a username, or false, not sure how to access that?

        passport.authenticate('localLogin')(mockReq, mockRes, next);

       // if I comment out the 'logIn' function above and make an explicit function here I can see the username being returned, but of course it's inside the function closure: 

       passport.authenticate('localLogin', function(err, user){
        // I can see here that the username is correct:
        console.log(user)
    })(mockReq, mockRes, next);

        expect(requestPromiseStub).to.have.been.called;


    });

    });

我很确定我忽略了一些非常简单的事情。愚蠢,但我似乎无法使用passport.authenticate的语法来获得正常的回调包装。 :(

1 个答案:

答案 0 :(得分:2)

配置/ passport.js



var rp = require('request-promise');
var passport = require('passport');
var LocalStrategy = require('passport-local').Strategy;

module.exports = function () {
  passport.use('local', new LocalStrategy({
    usernameField: 'username',
    passwordField: 'password'
  },
  function (username, password, done) {
    console.log('logic blah blah blah here, uses two request-promise calls');
    return done(null, username);
  }));
};




test.js



var chai = require('chai');
var expect = require('chai').expect;
var sinon = require('sinon');
var proxyquire = require('proxyquire');
var passport = require('passport');
var sinonChai = require('sinon-chai');

chai.use(sinonChai);

describe('it should get user account from the API', function () {
  it('should be able to access passport authenticate', function () {
    // configure request and response
    var mockReq = {
      body: {
        username: 'johndoe',
        password: 'secret'
      },
      logIn: function () {}
    };

    var mockRes = {};

    // configure request-promise
    var requestPromiseStub = sinon.stub();

    requestPromiseStub
      .onCall(0).returns(Promise.resolve({
        userId: 138
      }))
      .onCall(1).returns(Promise.resolve({
        userName: 'johndoe',
        status: 0
      }));

    var overrides = {
      'request-promise': requestPromiseStub
    };
    proxyquire('./passport.js', overrides)();
    passport.authenticate('local')(mockReq, mockRes);

    // ASSERTS HERE
    //expect(requestPromiseStub).to.have.been.called();
 });
});