The problem
I am unit testing a directive has no controller or template, only a link
function. The directive requires ngModel
and calls one of its functions in the link
function. I want to spy on ngModel
in my unit tests to ensure the right function is being called.
The code
Directive:
angular.module('some-module').directive('someDirective', function() {
return {
restrict: 'A',
require: 'ngModel',
link: function(scope, element, attr, controller) {
controller.doSomething(); //Calls some random function on the ngModel controller
}
};
});
What I've tried
I've tried to inject a spy ngModel
like this:
beforeEach(module(function($provide) {
$provide.factory('ngModelDirective', function() {
return {};
});
$provide.factory('ngModelController', function() {
return function() {};
});
}));
As I discovered on this question, trying to override built-in properties causes an error to be thrown, and is bad practice.
So then I tried to test the directive the way the Angular docs say to:
var $scope = $rootScope.$new();
var element = $compile('<div some-directive></div>')($scope);
And spy on NgModelController
like this:
var ngModelControllerSpyDoSomething = sinon.spy(element.controller('ngModel'), 'doSomething');
But this doesn't work, because one $compile
is run, it executes the link
function, so I'm not spying on it until it's too late (the spy is coming back as never having been called). This is also the case if I put $scope.$digest();
before or after creating the spy.