2013-07-09 42 views
3

在使用Node.js(CompoundJS + PassportJS)構建的應用程序中,如何在鎖定的控制器上運行Mocha測試並要求登錄?我嘗試過使用Superagent,但沒有太多的運氣,並且使用它需要運行服務器來運行測試。我已經非常接近這種方法,但不想讓服務器運行來運行單元測試。如何使用Node.js和Passport設置Mocha測試

我也試過包括護照和使用request.login的方法,我最終在一個點,我不斷收到錯誤passport.initialize()中間件未被使用。

我試圖堅持生成的CompoundJS測試,這些測試工作很好,直到涉及身份驗證。默認CompoundJS測試運行init.js文件,該文件將是不錯的處理身份驗證並以某種方式提供給每個控制器測試:

require('should'); 
global.getApp = function(done) { 
    var app = require('compound').createServer() 
    app.renderedViews = []; 
    app.flashedMessages = {}; 

    // Monkeypatch app#render so that it exposes the rendered view files 
    app._render = app.render; 
    app.render = function(viewName, opts, fn) { 
     app.renderedViews.push(viewName); 

     // Deep-copy flash messages 
     var flashes = opts.request.session.flash; 
     for (var type in flashes) { 
      app.flashedMessages[type] = []; 
      for (var i in flashes[type]) { 
       app.flashedMessages[type].push(flashes[type][i]); 
      } 
     } 

     return app._render.apply(this, arguments); 
    } 

    // Check whether a view has been rendered 
    app.didRender = function(viewRegex) { 
     var didRender = false; 
     app.renderedViews.forEach(function(renderedView) { 
      if (renderedView.match(viewRegex)) { 
       didRender = true; 
      } 
     }); 
     return didRender; 
    } 

    // Check whether a flash has been called 
    app.didFlash = function(type) { 
     return !!(app.flashedMessages[type]); 
    } 

    return app; 
}; 

控制器/ users_controller_test.js

var app, 
    compound, 
    request = require('supertest'), 
    sinon = require('sinon'); 

/** 
* TODO: User CREATION and EDITs should be tested, with PASSPORT 
* functionality. 
*/ 

function UserStub() { 
    return { 
     displayName: '', 
     email: '' 
    }; 
} 

describe('UserController', function() { 
    beforeEach(function(done) { 
     app = getApp(); 
     compound = app.compound; 
     compound.on('ready', function() { 
      done(); 
     }); 
    }); 

    /** 
    * GET /users 
    * Should render users/index.ejs 
    */ 
    it('should render "index" template on GET /users', function(done) { 
     request(app) 
      .get('/users') 
      .end(function(err, res) { 
       res.statusCode.should.equal(200); 
       app.didRender(/users\/index\.ejs$/i).should.be.true; 
       done(); 
      }); 
    }); 

    /* 
    * GET /users/:id 
    * Should render users/index.ejs 
    */ 
    it('should access User#find and render "show" template on GET /users/:id', 
     function(done) { 
      var User = app.models.User; 

      // Mock User#find 
      User.find = sinon.spy(function(id, callback) { 
       callback(null, new User); 
      }); 

      request(app) 
       .get('/users/42') 
       .end(function(err, res) { 
        res.statusCode.should.equal(200); 
        User.find.calledWith('42').should.be.true; 
        app.didRender(/users\/show\.ejs$/i).should.be.true; 

        done(); 
       }); 
     }); 
}); 

這些都失敗與AssertionError: expected 403 to equal 200AssertionError: expected false to be true

回答

0

我使用了mocking passport.initialize,一個測試幫助器和com上的監聽器的組合磅配置事件。

這提供了兩件事情:

  1. DRY - 跨控制器測試beforeEach代碼重用。
  2. 不顯眼的測試 - 模擬passport.initialize,所以我沒有必要修改基於測試的配置。

在測試/ init.js我添加的方法,以模擬passport.initialize **:

http://hackerpreneurialism.com/post/48344246498/node-js-testing-mocking-authenticated-passport-js

// Fake user login with passport. 
app.mockPassportInitialize = function() { 
    var passport = require('passport'); 
    passport.initialize = function() { 
     return function (req, res, next) { 
      passport = this; 
      passport._key = 'passport'; 
      passport._userProperty = 'user'; 
      passport.serializeUser = function(user, done) { 
       return done(null, user.id); 
      }; 
      passport.deserializeUser = function(user, done) { 
       return done(null, user); 
      }; 
      req._passport = { 
       instance: passport 
      }; 
      req._passport.session = { 
       user: new app.models.User({ id: 1, name: 'Joe Rogan' }) 
      }; 

      return next(); 
     }; 
    }; 
}; 

然後,我添加一個:

**在發現它helpers.js文件在每個控制器中調用:

module.exports = { 
    prepApp: function (done) { 
     var app = getApp(); 
     compound = app.compound; 
     compound.on('configure', function() { app.mockPassportInitialize(); }); 
     compound.on('ready', function() { done(); }); 
     return app; 
    } 
}; 

這將在每個控制器的beforeEach被調用:

describe('UserController', function() { 
    beforeEach(function (done) { 
     app = require('../helpers.js').prepApp(done); 
    }); 
    [...] 
}); 
+0

由於得到一個錯誤時,第一控制器的測試運行:{[錯誤:連接ECONNREFUSED]代碼:「ECONNREFUSED」,錯誤號:「ECONNREFUSED」,系統調用: 'connect'} – Michael

+1

確保使用'init.js'運行mocha:'mocha test/init.js test/controllers/users_controller.test.js' – absynce

+0

另外,驗證prepApp函數是否正在使用'console.log ('prepApp');'prepApp'頂部的''行。 – absynce

相關問題