假设我有以下内容:
LIB /模块/ module1.js
function deleteFutureAppointments() {
Appointment.findAll(
{ where:
{
pro_id, client_id, from_datetime_utc: {
$gt: new Date()
}
}
})
.then((appointments) => {
if (!appointments) {
return new Promise((resolve) => resolve());
}
const promises = appointments.map((id) => {
const appointmentQuery = { where: { client_id } };
const appointmentSMIQuery = { where: { appointment_id: id.get("appointment_id") } };
return AppointmentMedia.destroy(appointmentSMIQuery)
.then((result) => {
if (result) {
removeAppointmentMedia.push(id.get("appointment_id"));
}
AppointmentService.destroy(appointmentSMIQuery);
})
.then(() => IndexAppointmentCalendar.destroy(appointmentSMIQuery))
.then(() => Appointment.destroy(appointmentQuery));
});
return Promise.all(promises);
})
.catch((err) => {
next(err);
});
}
现在让我们说我在另一个目录中有一组测试,例如的测试/ testModule1.js 即可。从这个文件中,我创建了一个var m2 = require('module2');
module.exports = function(){
return {
// ...
get: function(cb){
m2.someMethod(params, function(error, data){
if(error){
cb(error)
}
cb(null, data)
})
},
// ...
}
}
的实例来执行一些测试。
我想从文件 testModule1.js 中模拟module1
传递给它的回调函数(不是m2.someMethod
函数)的对象。
我调查了Sinon.js,但我无法想办法做到这一点。实际上,我甚至可能吗?
感谢。
答案 0 :(得分:1)
您可以使用proxyquire
之类的内容,但我不喜欢修改内置require
。
就个人而言,我建议重写代码以使用依赖注入:
module.exports = function(m2){
return {
// ...
get: function(cb){
m2.someMethod(params, function(error, data){
if(error){
cb(error)
}
cb(null, data)
})
},
// ...
}
}
请注意,我已将m2
移动为导出函数中的参数。然后在其他地方(应用程序,主要或其他),你可以这样做:
var module1Creator = require('module1');
var module2 = require('module2');
var module1 = module1Creator(module2);
然后当你需要测试它时......
var module1Creator = require('module1');
// inject the "fake" version containing test data, spies, etc
var module2Mocked = require('module2mock');
var module1 = module1Creator(module2mocked);
答案 1 :(得分:0)
我会非常同意改变设计,并且正如@dvlsg所建议的,DI也是我的选择。
但是,我正在进行的项目已经在移动中,并且具有相当大的规模。通过这种改变意味着巨大的人力成本,在这种情况下,可能不值得这样做。
作为一种解决方案,我已经意识到,一旦你执行require('someModule')
,就会加载 someModule 并将其存储为单例,在某种情况下全局缓存(我不完全理解这种机制,但我会调查它),如果你从另一个文件中require('someModule')
并不重要,你将收到缓存版本。
所以,如果在 lib / modules / module1.js 我做require('module2')
, module2 被加载并存储在这个缓存中,我可以{{ 1}}并在 tests / testModule1.js 中模拟它。这将反映何时调用 lib / modules / module1.js 中的require('module2')
。
为此,我使用Sinon.js在测试文件中创建了模拟。
上面的程序实际上解决了我的问题,以一种我不必改变整个设计的方式,我能够进行测试。这就是我发布这个作为答案的原因。但是,我不会在此将此设置为正确的答案,因为正如我之前所说,我不完全理解这种机制并且更改所需的模块不是一个好习惯。
我想看看其他开发者对此有什么看法,如果讨论得到接受,我最终会将其设置为正确。