2013-12-20 59 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

相关问题