angular JS unit testing a controller

痞子三分冷 提交于 2019-12-11 16:23:07

问题


I have a controller like this

    (function(){
        var app = angular.module('app', []);

        app.directive('test', function(){
            return {
                restrict: 'E',
                templateUrl: 'test.html',
                controller: ['$scope', function ($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';
        }
      }
    }];
    });

I am writing a unit test to this controller

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

  var $controller;

  beforeEach(inject(function(_$controller_){
    // The injector unwraps the underscores (_) from around the parameter names when matching
    $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('$scope', { $scope: $scope });
      $scope.password = 'longerthaneightchars';
      $scope.grade();
      expect($scope.strength).toEqual('strong');
    });
  });
});

I am ending up getting an error which says Error:[ng:areq] Argument '$scope' is not a function, got undefined

I am I going in the right way please help


回答1:


Your controller is defined as a part of your directive definition, and I do not believe that these can be unit tested independently of the directive themsleves.

If you want to unit test this controller, you should give it a separate name using angular's controller method, then use it in your directive by name. Then you can retrieve the controller using angular-mock's $controller service similar to how you do it now. the end result looks like:

app.controller('YourCtrl', ['$scope', function($scope) { ... }]);
app.directive('test', function() {
   return {
          ...
          controller: 'YourCtrl',
          ...
   }});

and in the test

var controller = $controller('YourCtrl', { $scope: $scope });

Here is a jsFiddle that puts it all together




回答2:


Here is how I would test the directive's controller. DEMO http://plnkr.co/edit/w9cJ6KDNDvemO8QT3tTN?p=preview

I would not import the controller. I would compile the directive and test the directive's controller.

describe('PasswordController', function() {
  var $scope;
  var element;

  beforeEach(module('MyApp'));

  beforeEach(
    inject(function($rootScope, $compile, $templateCache) {
      // Imports test.html
      var templateUrl = 'test.html';
      var req = new XMLHttpRequest();
      req.onload = function () {
        $templateCache.put(templateUrl, this.responseText);
      };
      req.open('get', templateUrl, false);
      req.send();

      $scope = $rootScope.$new(); 

      element = '<test></test>';
      // Compile the directive 
      element = $compile(element)($scope);

      // Call digest cycle
      $scope.$apply();
    }));

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



回答3:


You can't create a $scope by doing $scope = {}. Change your spec to this:

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

    var $controller, $rootScope;

    beforeEach(inject(function (_$controller_, _$rootScope_) {
            // The injector unwraps the underscores (_) from around the parameter names when matching
            $controller = _$controller_;
            $rootScope = _$rootScope_;
        }));

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


来源:https://stackoverflow.com/questions/33134566/angular-js-unit-testing-a-controller

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!