淺析Node.js中使用依賴注入的相關(guān)問題及解決方法
最近,我轉(zhuǎn)向使用依賴注入來幫助理解分離代碼的簡單途徑,并有助測試。然而,Node.js中的模塊依賴Node提供的系統(tǒng)API,這很難判斷私有依賴被恰當(dāng)?shù)氖褂谩R话愕囊蕾囎⑷牒茈y在這種情況下使用,但現(xiàn)在不要放棄希望。
requireCauses 問題
Node.js很容易依照需求導(dǎo)入依賴。它運(yùn)行的很好,并且比AMD模式加載器例如RequireJS要簡單。當(dāng)我們模擬那些依賴的時(shí)候問題就來了。如果Node.js中模型的加載是受控的,我們怎么做才能控制讓偽對象在測試期間被使用到?我們可以使用Node的vm模式,通過vm我們可以再新的上下文中加載模型。運(yùn)行在新的上下文中,我們可以控制需求反射出模型的方法。
解決方案
謝謝這篇文章, 現(xiàn)在可以給你提供一個(gè)相當(dāng)不錯(cuò)的解決方案. 代碼在下面:
var vm = require('vm');
var fs = require('fs');
var path = require('path');
/**
* Helper for unit testing:
* – load module with mocked dependencies
* – allow accessing private state of the module
*
* @param {string} filePath Absolute path to module (file to load)
* @param {Object=} mocks Hash of mocked dependencies
*/
exports.loadModule = function(filePath, mocks) {
mocks = mocks || {};
// this is necessary to allow relative path modules within loaded file
// i.e. requiring ./some inside file /a/b.js needs to be resolved to /a/some
var resolveModule = function(module) {
if (module.charAt(0) !== '.') return module;
return path.resolve(path.dirname(filePath), module);
};
var exports = {};
var context = {
require: function(name) {
return mocks[name] || require(resolveModule(name));
},
console: console,
exports: exports,
module: {
exports: exports
}
};
vm.runInNewContext(fs.readFileSync(filePath), context);
return context;
};
你也可以在 這里 下載代碼片段 . 雖然在不是在文章發(fā)布最多的代碼, 他仍然可以使用一些解釋. 當(dāng)我們測試時(shí), 我們要加載這個(gè)模塊進(jìn)入測試, 使用theloadModulefunction代替ofrequire加載模塊測試.
第一個(gè)參數(shù)filePath指定了我們要測試模型的查找位置。第二個(gè)參數(shù)mocks包含一個(gè)對象,對象的屬性名稱要和我們嘗試require的模型的名稱相匹配。那些屬性指定的值就是偽對象,用來代替一般被require的模型。
本質(zhì)上看就是用vm來加載和運(yùn)行模型在另一個(gè)“上下文”中。換句話說,我們重建了全局變量(例如require和exports)以便我們能控制它們。需要注意的是我們編寫了一個(gè)可用的新require函數(shù)。所做一切就是檢查一下用執(zhí)行的名字是否有一個(gè)模擬的依賴,如果每日有,我就就把它委托給那個(gè)常用的require函數(shù)。
使用模塊加載器的例子
如果你還有點(diǎn)困惑,你可以看下面的代碼示例,看它在上下文中的使用,也許能幫你清楚一些。首先,我們創(chuàng)建一個(gè)簡單的模塊。
var fs = require('fs');
module.exports = {
// Do something with `fs`
}
想象一下這個(gè)很酷,對嗎?不管怎樣,現(xiàn)在我們測試那個(gè)模塊,但是我們要模擬fs來看看它是怎么在內(nèi)部使用的。
// Jasmine's syntax http://pivotal.github.com/jasmine/
describe('someModule', function() {
var loadModule = require('module-loader').loadModule;
var module, fsMock;
beforeEach(function() {
fsMock = {
// a mock for `fs`
};
// load the module with mock fs instead of real fs
module = loadModule('./web-server.js', {fs: fsMock});
});
it('should work', function() {
// a test that utilizes the fact that we can now control `fs`
});
});
主要注意是在7至12行,我們?yōu)閒s創(chuàng)建了一個(gè)偽對象并使用我們新的loadModule函數(shù)將這個(gè)使用的對象聯(lián)系到上面的小模塊中(我的意思是真棒!請記住,這是真棒,對不對?)。
相關(guān)文章
在?node?中使用?koa-multer?庫上傳文件的方式詳解
本文主要介紹了上傳單個(gè)文件、多個(gè)文件,文件數(shù)量大小限制、限制文件上傳類型和對上傳的圖片進(jìn)行不同大小的裁剪,對node使用?koa-multer?庫上傳文件相關(guān)知識感興趣的朋友一起看看吧2024-01-01
快速刪除 node_modules 目錄的集中方法(多種方法)
本文介紹了三種快速刪除node_modules目錄的方法:使用rimraf工具、通過npx運(yùn)行rimraf以及在Windows命令提示符中使用del命令,每種方法都適合不同的操作系統(tǒng)和使用場景2024-11-11
node.js結(jié)合webSocket實(shí)現(xiàn)聊天室
于Node.js和WebSocket的聊天室,主要包括前端頁面,主要是用戶操作的頁面,還包括后臺數(shù)據(jù)通信以及邏輯處理,具有一定的參考價(jià)值,感興趣的可以了解一下2023-08-08
nodejs通過phantomjs實(shí)現(xiàn)下載網(wǎng)頁
這篇文章主要介紹了nodejs通過phantomjs實(shí)現(xiàn)下載網(wǎng)頁的方法,有需要的小伙伴可以參考下。2015-05-05
React和Node.js快速上傳進(jìn)度條功能實(shí)現(xiàn)
這篇文章主要為大家介紹了React和Node.js快速上傳進(jìn)度條功能實(shí)現(xiàn)示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-03-03
基于NodeJS的前后端分離的思考與實(shí)踐(二)模版探索
在傳統(tǒng)的開發(fā)模式中,瀏覽器端與服務(wù)器端是由不同的前后端兩個(gè)團(tuán)隊(duì)開發(fā),但是模版卻又在這兩者中間的模糊地帶。因此模版上面總不可避免的越來越多復(fù)雜邏輯,最終難以維護(hù)。2014-09-09
Node.js之HTTP服務(wù)端和客戶端實(shí)現(xiàn)方式
這篇文章主要介紹了Node.js之HTTP服務(wù)端和客戶端實(shí)現(xiàn)方式,具有很好的參考價(jià)值,希望對大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-09-09

