简体   繁体   English

角单元测试:调用另一个控制器中定义的方法会抛出“未定义”不是错误

[英]Angular unit testing: Calling a method defined in another controller is throwing 'undefined' is not an error

I am trying to test an AngularJS file, but it can't call a method defined in another Controller. 我正在尝试测试AngularJS文件,但无法调用在另一个Controller中定义的方法。

In the MyPage file: 在MyPage文件中:

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. pageChecker()方法在MyApplication控制器的App.js中定义,并返回true或false。

For the sake of completeness: 为了完整起见:

$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()') 我得到“TypeError:'undefined'不是函数(评估'$ scope.pageChecker()')

I want to override the pageChecker method to always return true. 我想覆盖pageChecker方法以始终返回true。 How do I do this? 我该怎么做呢?

EDIT: Thanks to Dskh, I have my answer, with another tweak from me: 编辑:感谢Dskh,我得到了我的回答,还有我的另一项调整:

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();
  });
});

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. 当你执行$ rootScope。$ new()时,你自己创建$ scope,然后将它注入你使用$ controller()方法时创建的控制器中。

Therefore, if you want that method to always return true, you just need to create the method yourself: 因此,如果您希望该方法始终返回true,则只需要自己创建该方法:

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. 更多解释:当您的应用程序正在运行时,$ scope会通过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. 使用$ rootScope()。$ new()将为您提供像$ watch或$ on这样的角度方法,但是您需要自己重新创建自己的方法。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM