Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Unit Testing private functions in AngularJS Directive

How do I unit test a function that is defined inside a directive like the following myFunc?

angular.module('myApp')
  .directive('myDir', [function () {

    var myFunc = function (arg) {
      // code in here.
    };

    return {
      restrict: 'A',
      scope: { },
      link: function (scope, element) {

      }
    };
  }]);

Or how do you define testable directive specific functions that I don't want to expose outside of the directive?

like image 778
mkhatib Avatar asked Jan 10 '14 08:01

mkhatib


2 Answers

The most common approach is to not test private methods, but instead test the public interfaces that expose their behaviour. This means that your unit test becomes a contract for your public interface.

You've stated that you don't want to expose outside of the directive but of course the other option is to extract this logic into some service myDirService and perform your logic there. In that case you'll be able to test in isolation.

like image 154
eddiec Avatar answered Sep 21 '22 04:09

eddiec


As pointed out by @eddiec, ideally we shouldn't be in a situation where we need to test private methods, but we don't live in an ideal world.

The way I've found that works is by putting all private vars inside a private object - say model and then have a getter function to access any of it's properties. The scope is accessible from any jasmine test once you compile the directive.

angular.module('myApp').directive('myDir', [function() {

return {
    restrict: 'A',
    scope: {

    },
    link: function(scope, element) {
        var model = {
            myPrivateVar: 'myValue'
        };

        model.myPrivateFunction = function(arg) {
            // work with arg
        };

        scope.getVal = function(prop, args) {
            // Getter function to access any private variables
            if (model.hasOwnProperty(prop)) {
                // If the requested var exists, return it.
                return args ? model[prop](args) : model[prop];
            }
            return null;
        };

    }
};
}]);

I'm still not super happy with this solution, but it works for now.

like image 25
kayasky Avatar answered Sep 19 '22 04:09

kayasky