jaredhanson / electrolyte

Elegant dependency injection for Node.js.
MIT License
564 stars 61 forks source link

Using custom resolvers to substitute components for testing and other purposes #76

Open cstavaru opened 3 years ago

cstavaru commented 3 years ago

Hello,

First I would like to say that I really appreciate your work on many Javascript projects, I learned a lot from how you use the full power of Javascript in simple and elegant ways in PassportJS and other projects. I especially like the almost complete extensibility you build into your frameworks. I use the Electrolyte framework since a few months ago and I have to say it's yet another brilliant piece of software. Ok, so enough of this :)

I have an issue related to replacing components with mockups (or other components) for testing purposes. Sometimes I need to replace a component not with a mockup, but with another component from the same assembly or from another assembly. Example: I need to replace a KMS client for an online service with an in-memory KMS in order to perform the tests without having to connect to an online service.

One way to do this is to use a custom assembly function that receives component ids and substitutes them with already created components previously annotated as literal. (aka container.use(assemblyLoadFunction)).

But the most elegant way I found is to use a custom resolver which substitutes component ids with other ids of mockup components. However, there is an issue here, the "id" resolver is already the first resolver in the list and I cannot make the system to use my resolver before that (unless I would modify my components to use special characters in required component ids which would not be a feasible solution for many reasons).

I would suggest adding the resolvers in reverse order (just like you do with assemblies on container.use()). So, in container.js, the method

Container.prototype.resolver = function(fn) { this._resolvers.push(fn); }

would be more useful if it would look like this:

Container.prototype.resolver = function(fn) { this._resolvers.unshift(fn); }

This way the custom resolvers would be called before the default id resolver and it would add to the extensibility of the framework.

Of course, this can be hacked right now with accessing the internal this._resolvers array which is what I am currently doing.

I'm not sure if this would break current projects but I dare to say it would not, given the fact that you have suggested custom resolvers to use special characters in component ids.

Thanks !