2013-12-20 87 views
4

我們有一些我們想要測試的node.js代碼。這些是返回函數的模塊(module.exports = function(){...})。在函數內部需要一些其他模塊。現在我們要模擬這些模塊。看下面的例子:模擬模塊,它在node.js中返回一個函數

// userRepo.js 
module.exports = function(connection) { 
    // init the repo 
    var repo = DB.connect(connection);  

    // add validation function 
    repo.validate = function(data, cb) { 
     // do validation stuff 
     cb(error, result); 
    }; 

    return repo; 
}; 

// userController.js 
module.exports = function(config) { 
    var repo = require('userRepo.js')(config.connectionStringToUserDB) 
    var pub = {}; 

    pub.create = function(data, cb) { 
     repo.validate(data, function(err, res) { 
      // do some stuff 
     }; 
    }; 

    return pub; 
} 

// the test 
var sut = require('userController.js')(anyConfig); 

sut.create({}, function(err, res) { 
    // do some assertions here 
}; 

所以在測試中我們想模擬/存根函數repo.validate()。但直到現在我們還是沒有辦法做到這一點。我們測試的所有node.js模擬框架/庫都可以模擬一個模塊,然後您可以覆蓋導出。但在我們的例子中,模塊返回一個函數,而在控制器中,回購已經實例化。

我希望我的解釋是可以理解的:-)

感謝您的任何幫助。

回答

2

我不認爲你可以解決這個問題,而無需改變代碼中的內容。這是因爲repo變量是userRepo.js的私人變量。不過,我真的很喜歡這種情況,因爲現在你發現模塊設計不正確,無法完全測試。我會這樣寫。

// userRepo.js 
module.exports = function(connection) { 

    var api = {}, repo; 

    api.setRepo = function(r) { 
     repo = r; 
    } 
    api.getRepo = function() { 
     return repo; 
    } 
    api.init = function() { 

     // init the repo 
     repo = repo || DB.connect(connection); 

     // add validation function 
     repo.validate = function(data, cb) { 
      // do validation stuff 
      cb(error, result); 
     }; 

    } 

    return api; 
}; 

所以,在做這樣的事情,你將能夠模型的處理repo varialbe和一個自定義的驗證方法通過自己的變種。當然,問題是,在您使用userRepo.js

var userRepo = require("./userRepo.js")(connection) 

var userRepo = require("./userRepo.js")(connection).init(); 

你應該改變的地方,但它值得。因爲在你的測試可能會寫:

var userRepo = require("./userRepo.js")(connection).setRepo(customRepo).init(); 

甚至

var userRepo = require("./userRepo.js")(connection); 
var repo = userRepo.getRepo(); 
repo.validate = function() { 
    // custom stuff here 
} 
userRepo.init(); 

所以我的建議是:之前就開始寫東西問自己:「我怎麼去測試它?」。

+0

你說得對。最好是注入或獲取/設置回購輕鬆嘲笑。我的問題是,當控制器被調用時,調用者不知道回購,只有控制器知道它。但我可以注入它,並使用默認情況下,當注入回購是空的。 – 4kochi

相關問題