So on a recent episode of nodeup, the topic came up where they were talking about when you have to deal with an external API or something, how do you test that efficiently? If you do the naive thing you’ll end up with tests that are fragile and take hours to run, because you’re calling out to the API every time you run a test. So there are a couple of ways to deal with this problem. You can on the one hand use something like nock and have it intercept your http calls and return something nice for testing without actually doing any http calls, or you can use set up your code in a dependency injected style and then you run 90% of your tests as true unit tests, not even needing to call out to the external API, and you have 10% of your tests being integration tests that do real calls out to APIs and external databases, etc. One of these styles is not really better than the other (and in fact they are complementary), but doing dependency injection is of general value for your codebase, so I’m going to talk about how to do it in js.
The basic rule with dependency injection is that you never call ‘new’ (or the equivalent in other languages) in your code that actually does work. You have code that does stuff, and then you have glue that ties those parts together. The glue is what allocates objects. The reason you don’t call new in your code is that doing this hard codes what you’re going to do. Instead of calling new, you take all of the objects you need as parameters either to a function, or to your constructor for your object.
Let’s make this a bit more practical. If you were going to call some random API, the code you would use might be like:
A traditional dependency injection style (which largely comes from java) might do the following:
So dependency injection adds some overhead, but the real benefit comes in testing. For version 1 above, you’d have to use nock or a similar tool to run tests without actually interacting with the service. For the others you might have to use mocks or fakes, but they can be very simple. For example a fake requestFactory for version 3 might be:
and the actual test would be something like:
Here are some talks on Dependency injection and testing: