2016-07-29 150 views
2

我在我的本地登录策略中使用存根/模拟(因为它调用外部API)进行单元测试,但我似乎无法进入要测试的函数它。如何单元测试护照本地策略? (sinon,proxyquire)

这是我的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; 


    }); 

    }); 

而且在配置/ passport.js功能的设置:

​​

据我所知道的,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; 


    }); 

    }); 

我敢肯定,我俯瞰很简单的东西&哑巴,但我似乎无法得到正常callbacky包装与护照的语法工作。认证。 :(

回答

1

配置/ 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(); 
 
}); 
 
});

+0

太谢谢你了!这是* *几乎为我工作。 .. :) mockReq中的'logIn:function(){}'是什么?我如何测试从passport.authenticate返回的值? (它应该返回一个用户。) – esperluette

+0

这是护照注入的护照功能。请参阅https://github.com/jaredhanson/passport/blob/master/lib/http/request.js 如果你删除了req.logIn,它将失败。 –

+0

请解释“我如何测试从passport.authenticate返回的值?” –