admin管理员组

文章数量:1410737

I am trying to test an AngularJS file, but it can't call a method defined in another Controller.

In the MyPage file:

angular.module('MyApplication').controller('MyPageCtrl', function ($scope, $rootScope) {
  if($scope.pageChecker) {
    $scope.doSomething();
  }
}

The pageChecker() method is defined in App.js, in the MyApplication controller, and returns true or false.

For the sake of pleteness:

$scope.pageChecker = function() {
  if(cookieCheck) {
    return true;
  }
  else {
    return false;
  }
};

The jasmine file is:

describe("Page check", function(){
  beforeEach(angular.mock.module('MyApplication'));

  beforeEach(angular.mock.inject(function ($rootScope, $controller) {
    var $scope = $rootScope.$new();
    $controller('MyPageCtrl', { $scope: $scope});
  }));

  it("should call $scope.doSomething", function(){
    spyOn($scope, "doSomething");
    $scope.doSomething();
    expect($scope.doSomething).toHaveBeenCalled();
  });
});

I get "TypeError: 'undefined' is not a function (evaluating '$scope.pageChecker()')

I want to override the pageChecker method to always return true. How do I do this?

EDIT: Thanks to Dskh, I have my answer, with another tweak from me:

describe("Page check", function(){

  var $scope; //declare here, else it is a local variable inside the beforeEach

  beforeEach(angular.mock.module('MyApplication'));

  beforeEach(angular.mock.inject(function ($rootScope, $controller) {
    $scope = $rootScope.$new();
    // define the overriding methods here
    $scope.pageChecker = function(){
      return true;
    };
    // end overriding methods here
    $controller('MyPageCtrl', { $scope: $scope});
  }));

  it("should call $scope.doSomething", function(){
    spyOn($scope, "doSomething");
    $scope.doSomething();
    expect($scope.doSomething).toHaveBeenCalled();
  });
});

I am trying to test an AngularJS file, but it can't call a method defined in another Controller.

In the MyPage file:

angular.module('MyApplication').controller('MyPageCtrl', function ($scope, $rootScope) {
  if($scope.pageChecker) {
    $scope.doSomething();
  }
}

The pageChecker() method is defined in App.js, in the MyApplication controller, and returns true or false.

For the sake of pleteness:

$scope.pageChecker = function() {
  if(cookieCheck) {
    return true;
  }
  else {
    return false;
  }
};

The jasmine file is:

describe("Page check", function(){
  beforeEach(angular.mock.module('MyApplication'));

  beforeEach(angular.mock.inject(function ($rootScope, $controller) {
    var $scope = $rootScope.$new();
    $controller('MyPageCtrl', { $scope: $scope});
  }));

  it("should call $scope.doSomething", function(){
    spyOn($scope, "doSomething");
    $scope.doSomething();
    expect($scope.doSomething).toHaveBeenCalled();
  });
});

I get "TypeError: 'undefined' is not a function (evaluating '$scope.pageChecker()')

I want to override the pageChecker method to always return true. How do I do this?

EDIT: Thanks to Dskh, I have my answer, with another tweak from me:

describe("Page check", function(){

  var $scope; //declare here, else it is a local variable inside the beforeEach

  beforeEach(angular.mock.module('MyApplication'));

  beforeEach(angular.mock.inject(function ($rootScope, $controller) {
    $scope = $rootScope.$new();
    // define the overriding methods here
    $scope.pageChecker = function(){
      return true;
    };
    // end overriding methods here
    $controller('MyPageCtrl', { $scope: $scope});
  }));

  it("should call $scope.doSomething", function(){
    spyOn($scope, "doSomething");
    $scope.doSomething();
    expect($scope.doSomething).toHaveBeenCalled();
  });
});
Share Improve this question edited Jan 2, 2014 at 16:48 Jezcentral asked Jan 2, 2014 at 15:20 JezcentralJezcentral 4224 silver badges18 bronze badges 2
  • 1 I think there's a typo in the question, I don't see any call to $scope.pageChecker() as a function call. It looks like your controller calls the $scope.pageChecker method as part of the controller instantiation, and when you're providing the scope object in controller creation in the test it indeed doesn't have a pageChecker method – Eitan Peer Commented Jan 2, 2014 at 15:34
  • Good catch, Eitan, but not the cause of the problem. This was a names-have-been-changed-to-protect-the-innocent version of my code, as my employer would not like me posting actual code. :) – Jezcentral Commented Jan 2, 2014 at 16:00
Add a ment  | 

1 Answer 1

Reset to default 7

You create the $scope yourself when you do $rootScope.$new(), and then you inject it into the controller you create when you use the $controller() method.

Therefore, if you want that method to always return true, you just need to create the method yourself:

beforeEach(angular.mock.inject(function ($rootScope, $controller) {
    var $scope = $rootScope.$new();

    $scope.doSomething = function(){
        return true;
    };

    $controller('MyPageCtrl', { $scope: $scope});
  }));

Some more explanation: When your app is running for real, $scope is injected automatically into your controller by angular. In your test you are just testing your controller in isolation, so you need to create the scope object yourself and fake any behaviour you want from it. Using $rootScope().$new() will give you the angular methods like $watch or $on, but you need to recreate your own methods yourself.

本文标签: