Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Testing non-scope functions in Angular Controller with Jasmine

Jasmine is one of the most widely used testing frameworks to unit-test javascript code in BDD manner. I tried to use it for AngularJS components testing. AngularJS documentation provides the following sample code

describe('PasswordController', function() {
  beforeEach(module('app'));
  var $controller;

  beforeEach(inject(function(_$controller_){
    $controller = _$controller_;
  }));

  describe('$scope.grade', function() {
    it('sets the strength to "strong" if the password length is >8 chars', function() {
      var $scope = {};
      var controller = $controller('PasswordController', { $scope: $scope });
      $scope.password = 'longerthaneightchars';
      $scope.grade();
      expect($scope.strength).toEqual('strong');
    });
  });
});

So the code above uses angular mock library and via dependency injection processes a scope through a controller. Now I have a scope object with functions and objects my controller assigned to it. I can test it well. Happy.

Now the interesting part is if I want to test the functions which are not linked to the scope. For example, the doSomethingVeryCoolThatNeedsTesting function below

angular.module('app', [])
.controller('PasswordController', function PasswordController($scope) {
  $scope.password = '';
  $scope.grade = function() {
    var size = $scope.password.length;
    if (size > 8) {
      $scope.strength = 'strong';
    } else if (size > 3) {
      $scope.strength = 'medium';
    } else {
      $scope.strength = 'weak';
    }

   function doSomethingVeryCoolThatNeedsTesting() {
    ....  
   }

  };
});

It seems that whenever I use $controller('PasswordController', { $scope: $scope }); it returns a populated $scope object and undefined controller object.

TL;DR

Is there a way I can test Angular Controller functions which are not linked to the scope?

like image 480
Arturs Vancans Avatar asked Jul 01 '15 10:07

Arturs Vancans


1 Answers

No. As far as you don't expose the inner controller functions to the outside world those functions are private see the revealing module pattern.

So the problem is not angular neither the testing framework, The problem is the javascript language itself.

If you want to test an inner function you have to make it visible to the outside. The options are:

  1. Exposed it on the $scope object
  2. Expose onto any other global object which is strongly discouraged and might be not reachable by the test
like image 137
borja gómez Avatar answered Nov 15 '22 01:11

borja gómez