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.