In short, you don't need a dependency injection container or service locater like you would in C#/Java. Since Node.js, leverages the module pattern
, it's not necessary to perform constructor or property injection. Although you still can.
The great thing about JS is that you can modify just about anything to achieve what you want. This comes in handy when it comes to testing.
Behold my very lame contrived example.
MyClass.js
:
var fs = require('fs');
MyClass.prototype.errorFileExists = function(dir) {
var dirsOrFiles = fs.readdirSync(dir);
for (var d of dirsOrFiles) {
if (d === 'error.txt') return true;
}
return false;
};
MyClass.test.js
:
describe('MyClass', function(){
it('should return an error if error.txt is found in the directory', function(done){
var mc = new MyClass();
assert(mc.errorFileExists('/tmp/mydir')); //true
});
});
Notice how MyClass
depends upon the fs
module? As @ShatyemShekhar mentioned, you can indeed do constructor or property injection as in other languages. But it's not necessary in Javascript.
In this case, you can do two things.
You can stub the fs.readdirSync
method or you can return an entirely different module when you call require
.
Method 1:
var oldmethod = fs.readdirSync;
fs.readdirSync = function(dir) {
return ['somefile.txt', 'error.txt', 'anotherfile.txt'];
};
*** PERFORM TEST ***
*** RESTORE METHOD AFTER TEST ****
fs.readddirSync = oldmethod;
Method 2:
var oldrequire = require
require = function(module) {
if (module === 'fs') {
return {
readdirSync: function(dir) {
return ['somefile.txt', 'error.txt', 'anotherfile.txt'];
};
};
} else
return oldrequire(module);
}
The key is to leverage the power of Node.js and Javascript. Note, I'm a CoffeeScript guy, so my JS syntax might be incorrect somewhere. Also, I'm not saying that this is the best way, but it is a way. Javascript gurus might be able to chime in with other solutions.
Update:
This should address your specific question regarding database connections. I'd create a separate module to encapsulate your database connection logic. Something like this:
MyDbConnection.js
: (be sure to choose a better name)
var db = require('whichever_db_vendor_i_use');
module.exports.fetchConnection() = function() {
//logic to test connection
//do I want to connection pool?
//do I need only one connection throughout the lifecyle of my application?
return db.createConnection(port, host, databasename); //<--- values typically from a config file
}
Then, any module that needs a database connection would then just include your MyDbConnection
module.
SuperCoolWebApp.js
:
var dbCon = require('./lib/mydbconnection'); //wherever the file is stored
//now do something with the connection
var connection = dbCon.fetchConnection(); //mydbconnection.js is responsible for pooling, reusing, whatever your app use case is
//come TEST time of SuperCoolWebApp, you can set the require or return whatever you want, or, like I said, use an actual connection to a TEST database.
Do not follow this example verbatim. It's a lame example at trying to communicate that you leverage the module
pattern to manage your dependencies. Hopefully this helps a bit more.