Models with dependency injection in Nodejs

What is the best practice for injecting dependencies into models? And especially, what if their getter are asynchronous, as with mongodb.getCollection()?

The point is to inject dependencies once with

var model = require('./model')({dep1: foo, dep2: bar});

and call all member methods without having to pass them as arguments. Neither do I want to have each method to begin with a waterfall of async getters.

I ended up with a dedicated exports wrapper that proxies all calls and passes the async dependencies.

However, this creates a lot of overhead, it's repetitive a lot and I generally do not like it.

var Entity = require('./entity');

function findById(id, callback, collection) {
    // ...
    // callback(null, Entity(...));
};

module.exports = function(di) {
    function getCollection(callback) {
        di.database.collection('users', callback);
    };

    return {
        findById: function(id, callback) {
            getCollection(function(err, collection) {
                findById(id, callback, collection);
            });
        },
        // ... more methods, all expecting `collection`
    };
};

What is the best practice for injecting dependencies, especially those with async getters?

If your need is to support unit testing, dependency injection in a dynamic language like javascript is probably more trouble than it's worth. Note that just about none of the modules you require from others are likely to use the patterns for DI you see in Java, .NET, and with other statically compiled languages.

If you want to mock out behavior in order to isolate specific units of code for testing, see the 'sinon' module http://sinonjs.org/. It allows you to dynamically swap in/out interceptors that can either spy on method calls or replace them altogether. In practice, you would write a mocha test where you require your module, then require a module that's leveraged in your code. Use sinon to spy or stub a method on that module and as a result, you can isolate your code.

There is one scenario where I've not been able to completely isolate 3rd party code with sinon, and this is when the act of require()ing a module executes some behavior that you don't want to run in your test. For that scenario, I made a super simple module called 'mockrequire' https://github.com/mateodelnorte/mockrequire that allows you to provide an inline mock to be required instead of the actual module. You can provide a mock that uses spy or stub from sinon and have the same syntax and patterns as all the rest of your tests.

Hopefully this answers the underlying question from your post. ;)

In very simple situations, you could simply export a function that modifies objects in your file scope and returns your actual exports object, but if you want to inject more variably (i.e. for more than one use from your app) it's generally better to create a wrapper object like you have done.

You can reduce some overhead and indentation in some situations by using a wrapper class instead of a function returning an object.

For instance

function findById(id, callback, collection) {
  // ...
  // callback(null, Entity(...));
};

function Wrapper(di) {
  this.di = di;
}
module.exports = Wrapper; // or do 'new' usage in a function if preferred

Wrapper.prototype.findById = function (id, callback) {
  // use this.di to call findById and getCollection
}, // etc

Other than that, it's not a whole lot you can do to improve things. I like this approach though. Keeps the state di explicit and separate from the function body of findById and by using a class you reduce the nesting of indentation a little bit at least.