Testing is given much emphasis in the Ember.js community, and testing tools have showed steady progress to reduce the cost of writing tests of all types.
Lauren Tan wrote a great post about how Dependency Injection (DI) can be used to decouple a parent component from the internals of its child components. One of the gains of doing so is that the parent component becomes more focused and thus easier to test.
In this post, I’m doing something similar, although much simpler. I want to show you how to use DI in a simple helper function to make it easier to test.
Just your ordinary, run-of-the-mill function
Although the helper is an Ember (template) helper, the concepts could be very easily transferred to other frameworks, libraries and even languages.
I recently had to modify a
normalizeText helper function that looked
1 2 3 4 5 6 7 8
(I realize the above code does not handle a text value of
The real code does but I want to keep the code examples to the minimum necessary
to get my point across.)
Comparing objects to objects
Its test was quite simple and straightforward:
1 2 3 4 5 6 7 8 9 10
The problem with that test is that we compare two
instances (returned by
Ember.String.htmlSafe) which are different even if
the strings they wrap, their value, is the same:
1 2 3
We’re, however, interested in the equality of the strings. If only there was a
way to replace that pesky
Ember.String.htmlSafe call from the call site…
DI to the rescue
This is exactly what Dependency Injection can help us do. Instead of hard-coding that “sanitizer” function dependency, the function could take it as a parameter so that callers could inject it. Usually DI examples use (and thus inject) class names or object instances but it is important to realize that the injected param could be very “primitive”, like a simple function.
So here is how I rewrote the function:
1 2 3 4 5 6 7 8 9 10 11
Notice how easy ES2015 destructuring makes the assignment of the sanitizer function:
sanitizer key was present in
params, then it will have a value of
Ember.String.htmlSafe, the default behavior.
The call from the test can now override the default behavior of sending the
normalized text through
Ember.String.htmlSafe by passing in a “no-op”
1 2 3 4 5 6 7 8 9 10 11 12 13 14
We’re now comparing simple strings which place nicely with
===), and our test now passes.
Code modifications introduced for the sake of testing usually also improve the
non-testing aspect. Here, we made it possible to pass any function before we
return the normalized text. We could, for example, use this to replace the
<span>s, if we so wish.