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', { |