Introduction
Learn about the related concepts in Dependency Injection , let's take a look at how to use dependency injection in Node.
Original: Dependency Injection in Node.js
text
Dependency injection is a software design pattern in which one or more dependencies (or services) are injected or passed by reference to dependent objects.
Reasons to use dependency injection
Decoupling
Dependency injection reduces the coupling of your modules, resulting in a more maintainable code base.
Facilitate unit testing
You can pass them to the modules you want to use instead of using hard-coded dependencies. In most cases, you don't need to use a module like proxyquire
Rapid development
Using dependency injection, after defining the interface, you can easily work without any merge conflicts.
How to use Node.js dependency injection
First, let's see how to write your application without using dependency injection, and how to transform it.
No dependency injection example module used
// team.js
var User = require('./user');
function getTeam(teamId) {
return User.find({teamId: teamId});
}
module.exports.getTeam = getTeam;
A simple test looks like this:
// team.spec.js
var Team = require('./team');
var User = require('./user');
describe('Team', function() {
it('#getTeam', function* () {
var users = [{id: 1, id: 2}];
this.sandbox.stub(User, 'find', function() {
return Promise.resolve(users);
});
var team = yield team.getTeam();
expect(team).to.eql(users);
});
});
What we did here is to create a file named team.js
, which can return a list of users belonging to a single team. For this, we need the User
model, so we can call its find
method, which returns a list of users.
It looks good, right? But when testing, we must use test stubs.
In the test file, we also need the require
User
model, so that it can stub its find
method. Please note that we are using the sandbox feature here, so there is no need to manually restore the original function after the test is run.
Use dependency injection example modules
// team.js
function Team(options) {
this.options = options;
}
Team.prototype.getTeam = function(teamId) {
return this.options.User.find({teamId: teamId})
}
function create(options) {
return new Team(options);
}
You can test this file with the following test cases:
// team.spec.js
var Team = require('./team');
describe('Team', function() {
it('#getTeam', function* () {
var users = [{id: 1, id: 2}];
var fakeUser = {
find: function() {
return Promise.resolve(users);
}
};
var team = Team.create({
User: fakeUser
});
var team = yield team.getTeam();
expect(team).to.eql(users);
});
});
Okay, so what is the difference between the version of dependency injection and the previous version? The first thing you can notice is factory pattern : we use it to inject options/dependencies into newly created objects-this is where we can inject the User
model.
In the test document, we have to create a representation User
model fake model , then we simply by passing it to Team
model create
function to inject this model. It's simple, right?
Dependency injection in real projects
You can find examples of dependency injection in many open source projects. For example, most Express/Koa middleware you use in your daily work use the same method.
Express middleware
var express = require('express');
var app = express();
var session = require('express-session');
app.use(session({
store: require('connect-session-knex')()
}));
The above code snippet uses factory mode dependency injection: pass the connect-session-knex
module to the session middleware-it must implement an interface, and the session
module will call the interface.
In this example, the connect-session-knex
module must implement the following methods:
store.destroy(sid, callback)
store.get(sid, callback)
store.set(sid, session, callback)
Hapi plugin
The same concept can also be found in Hapi-the following example uses the handlebars
module as a view engine into Hapi.
server.views({
engines: {
html: require('handlebars')
},
relativeTo: __dirname,
path: 'templates'
});
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。