Let's take a function with 3 arguments that computes and logs a sum of two numbers
1 | function logSum(a, b, log) { |
Passing a logger function as a log
argument makes unit testing logSum very easy
1 | QUnit.test('log sum', function (assert) { |
Dependency injection #
This pattern is called dependency injection - providing dynamic arguments to the function, widely used by AngularJs for example. Dependency injection has a run time executor which inspects a function and injects correct argument by name. Or it could be done via proxy function, like in heroin
1 | QUnit.test('log sum', function (assert) { |
What if we want to bind some arguments to the function, but leave others unchanged?
Partial argument binding #
We could use Function.bind
binding arguments to the function in left to right order
by position:
1 | QUnit.test('log sum', function (assert) { |
Notice we performed partial binding - only providing the first argument, leaving 2nd and 3rd arguments free. Can we do the same for dependency injection?
Partial dependency injection #
Yes, using heroin we can. If the dependency object does not contain an own property for an argument, it is left free and you can provide it during the execution
1 | QUnit.test('log sum', function (assert) { |
The cool thing is that argument for the dependency injection
does not matter, we could inject log
and b
, leaving a
in the middle free
1 | QUnit.test('log sum', function (assert) { |
Use case #
A good use case for partial dependency injection is in my
qunit-inject plugin. It allows one
to inject properties from a module into the individual unit tests, while still
leaving argument assert
free to be provided by the
runtime framework
1 | QUnit.module('QUnit.assert tests WITH injection', { |
qunit-inject creates a proxy for each unit test function, injecting
module's config, but since the config does not have assert
property,
the QUnit's runner sees only a proxy that expects assert
argument.
And if you are terribly evil, you can even inject your own assert from
the module, so that QUnit's assert argument is ignored.
1 | QUnit.module('Your assert', { |