express - 如何对 Passport 本地策略进行单元测试? (sinon,proxyquire)

标签 express passport.js sinon passport-local

我的本​​地 Passport 登录策略中有一些逻辑,我想使用 stub /模拟进行单元测试(因为它调用外部 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 并且只需要“通常” Passport 和 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 的语法一起使用。 :(

最佳答案

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

测试.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();
 });
});

关于express - 如何对 Passport 本地策略进行单元测试? (sinon,proxyquire),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38648577/

相关文章:

javascript - 如何使用 chai 和 sinon 测试方法是否重新抛出现有错误

jwt - 使用 Passport-jwt 和尾声,我的 req.user 为空

google-cloud-platform - 如何使用 sinon 、 mocha chai 模拟以下代码的响应

jquery - Node.js、Express、jQuery.param() - 从 JSON 中删除引号

Node.js 和 Mongodb

mysql - OAUTH2 用户 ID 是如何生成的?

javascript - 无法导出 E​​xpress 中的函数

Javascript 单元测试 Promise.all 同步

javascript - 如何访问server.js文件之外的应用程序?

javascript - 在 typescript 中使用express中的回调函数数组