Dependency Injection with ECMAScript 6

Make your JavaScript code easy testable.

Image for post
Image for post

Every now and then I stumble over new ideas and try to implement them. Last time a read a very good book (Simplifying JavaScript: Writing Modern JavaScript with ES5, ES6, and Beyond) about the new features of JavaScript that rises with ECMAScript 6 and the author claims that it would be a good idea to make your code better testable by simply using dependency injection.

Gotcha, yes, he was quite right. So how to acomplish this with ECMScript 6 in a usual manner, as a code snippet or simply a good practice?

After some experiments I found the following solution explained with a simple example for two modules logger and assert, something I was always missing in JavaScript.

First of all create a directory for every module you want to create.

In my case I create the directories assert and logger inside a utils directory.

In the next step we create our content for these directories. That is …

Image for post
Image for post

Wow a bunch of stuff for those little modules, but it follows simply a general rule. What does these files mean an do? Just a sec, I will explain.

First of all each directory contains the file with the real code, here assert.js and logger.js.

Second we have a test file for each of it in the same directory, due to the new style to keep everything together in one place.

And last but not least we have an index.js in each. What’s that?

The index.js has the role of an instance that puts everything together.

But let us start from the beginning with the real code that does something.

My first atempt to write an assert module looks like this.

Image for post
Image for post

As usual, I import the dependend moduls at first and use them later in the code. But now I want to be able to inject my dependency and that ist done as follows.

Image for post
Image for post

I define an internal api as a lamba function that returns the final api with the injected dependendy. Quite easy. Out of the box this api is not really functional, it misses the dependency. So let us create the great combinator, the index.js doing this.

Image for post
Image for post

What does it? It simply imports the dependency and creates the final api with it. It is exported in the last step — I love it.

To use it you have to import the index.js from the module that is done in the following way. And you see no index.js at all is used, because it is done automatically for you.

Image for post
Image for post

And what about the tests. Here we go.

Image for post
Image for post

Also very easy to do, you now can simply mock the dependencies. Therefore you have to import the plain api without the injected dependencies and inject your mock instead. Thats it, not more.

And here are the missing files to get the complete picture.

The logger api

Image for post
Image for post

the index.js for the logger

Image for post
Image for post

and the spec

Image for post
Image for post

Circular dependency

By the time you will get hit by the circular dependency problem. In its easiest form it shows up with two files like A and B with A imports B and B imports A. You probably can get rid of it using one of the following ideas:

  1. Add only those methods into a file that belongs together, has the same purpose. Mixing logging methods and methods to do math does not get together well.
  2. Try to get rid of it by moving the methods to another file in the same folder and import that directly.

So nothing more to say, I hope I could help a bit and you get the idea.

See you and happy coding.

Image for post
Image for post

ORCID

Developer since the 80'th, working at Forschungszentrum Jülich (http://www.fz-juelich.de) …

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store