0

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.

Community
  • 1
  • 1
A. Duff
  • 4,097
  • 7
  • 38
  • 69

1 Answers1

-1

You will have to add your spy to the $scope you are injecting into the $compile-Function and then link it within the actual directives HTMLngModel`, so:

var $scope = $rootScope.$new();
$scope.mySpy = // create a stub function with sinon here
var element = $compile('<div some-directive ng-model="mySpy"></div>')($scope);
David Losert
  • 4,652
  • 1
  • 25
  • 31
  • How would I check whether a property of `ngModel` had been called, then?The function that's being called is a property of `ngModel`, it's not on the thing the model is linked to. – A. Duff Mar 04 '15 at 15:11